TestController.cpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248
  1. /*
  2. * Copyright (C) 2010 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
  14. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  15. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
  17. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  18. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  19. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  21. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  22. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  23. * THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "config.h"
  26. #include "TestController.h"
  27. #include "PlatformWebView.h"
  28. #include "StringFunctions.h"
  29. #include "TestInvocation.h"
  30. #include <WebKit2/WKAuthenticationChallenge.h>
  31. #include <WebKit2/WKAuthenticationDecisionListener.h>
  32. #include <WebKit2/WKContextPrivate.h>
  33. #include <WebKit2/WKCredential.h>
  34. #include <WebKit2/WKIconDatabase.h>
  35. #include <WebKit2/WKNotification.h>
  36. #include <WebKit2/WKNotificationManager.h>
  37. #include <WebKit2/WKNotificationPermissionRequest.h>
  38. #include <WebKit2/WKNumber.h>
  39. #include <WebKit2/WKPageGroup.h>
  40. #include <WebKit2/WKPagePrivate.h>
  41. #include <WebKit2/WKPreferencesPrivate.h>
  42. #include <WebKit2/WKRetainPtr.h>
  43. #include <algorithm>
  44. #include <cstdio>
  45. #include <ctype.h>
  46. #include <stdlib.h>
  47. #include <string>
  48. #include <wtf/PassOwnPtr.h>
  49. #include <wtf/text/CString.h>
  50. #if PLATFORM(MAC)
  51. #include <WebKit2/WKPagePrivateMac.h>
  52. #endif
  53. #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
  54. #include "EventSenderProxy.h"
  55. #endif
  56. #if !PLATFORM(MAC)
  57. #include <WebKit2/WKTextChecker.h>
  58. #endif
  59. namespace WTR {
  60. const unsigned TestController::viewWidth = 800;
  61. const unsigned TestController::viewHeight = 600;
  62. const unsigned TestController::w3cSVGViewWidth = 480;
  63. const unsigned TestController::w3cSVGViewHeight = 360;
  64. // defaultLongTimeout + defaultShortTimeout should be less than 80,
  65. // the default timeout value of the test harness so we can detect an
  66. // unresponsive web process.
  67. static const double defaultLongTimeout = 60;
  68. static const double defaultShortTimeout = 15;
  69. static const double defaultNoTimeout = -1;
  70. static WKURLRef blankURL()
  71. {
  72. static WKURLRef staticBlankURL = WKURLCreateWithUTF8CString("about:blank");
  73. return staticBlankURL;
  74. }
  75. static TestController* controller;
  76. TestController& TestController::shared()
  77. {
  78. ASSERT(controller);
  79. return *controller;
  80. }
  81. TestController::TestController(int argc, const char* argv[])
  82. : m_verbose(false)
  83. , m_printSeparators(false)
  84. , m_usingServerMode(false)
  85. , m_gcBetweenTests(false)
  86. , m_shouldDumpPixelsForAllTests(false)
  87. , m_state(Initial)
  88. , m_doneResetting(false)
  89. , m_longTimeout(defaultLongTimeout)
  90. , m_shortTimeout(defaultShortTimeout)
  91. , m_noTimeout(defaultNoTimeout)
  92. , m_useWaitToDumpWatchdogTimer(true)
  93. , m_forceNoTimeout(false)
  94. , m_timeout(0)
  95. , m_didPrintWebProcessCrashedMessage(false)
  96. , m_shouldExitWhenWebProcessCrashes(true)
  97. , m_beforeUnloadReturnValue(true)
  98. , m_isGeolocationPermissionSet(false)
  99. , m_isGeolocationPermissionAllowed(false)
  100. , m_policyDelegateEnabled(false)
  101. , m_policyDelegatePermissive(false)
  102. {
  103. initialize(argc, argv);
  104. controller = this;
  105. run();
  106. controller = 0;
  107. }
  108. TestController::~TestController()
  109. {
  110. WKIconDatabaseClose(WKContextGetIconDatabase(m_context.get()));
  111. platformDestroy();
  112. }
  113. static WKRect getWindowFrame(WKPageRef page, const void* clientInfo)
  114. {
  115. PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
  116. return view->windowFrame();
  117. }
  118. static void setWindowFrame(WKPageRef page, WKRect frame, const void* clientInfo)
  119. {
  120. PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
  121. view->setWindowFrame(frame);
  122. }
  123. static bool runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, const void*)
  124. {
  125. printf("CONFIRM NAVIGATION: %s\n", toSTD(message).c_str());
  126. return TestController::shared().beforeUnloadReturnValue();
  127. }
  128. static unsigned long long exceededDatabaseQuota(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKStringRef, WKStringRef, unsigned long long, unsigned long long, unsigned long long, unsigned long long, const void*)
  129. {
  130. static const unsigned long long defaultQuota = 5 * 1024 * 1024;
  131. return defaultQuota;
  132. }
  133. void TestController::runModal(WKPageRef page, const void* clientInfo)
  134. {
  135. PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
  136. view->setWindowIsKey(false);
  137. runModal(view);
  138. view->setWindowIsKey(true);
  139. }
  140. static void closeOtherPage(WKPageRef page, const void* clientInfo)
  141. {
  142. WKPageClose(page);
  143. PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
  144. delete view;
  145. }
  146. static void focus(WKPageRef page, const void* clientInfo)
  147. {
  148. PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
  149. view->focus();
  150. view->setWindowIsKey(true);
  151. }
  152. static void unfocus(WKPageRef page, const void* clientInfo)
  153. {
  154. PlatformWebView* view = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
  155. view->setWindowIsKey(false);
  156. }
  157. static void decidePolicyForGeolocationPermissionRequest(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKGeolocationPermissionRequestRef permissionRequest, const void* clientInfo)
  158. {
  159. TestController::shared().handleGeolocationPermissionRequest(permissionRequest);
  160. }
  161. int TestController::getCustomTimeout()
  162. {
  163. return m_timeout;
  164. }
  165. WKPageRef TestController::createOtherPage(WKPageRef oldPage, WKURLRequestRef, WKDictionaryRef, WKEventModifiers, WKEventMouseButton, const void* clientInfo)
  166. {
  167. PlatformWebView* parentView = static_cast<PlatformWebView*>(const_cast<void*>(clientInfo));
  168. PlatformWebView* view = new PlatformWebView(WKPageGetContext(oldPage), WKPageGetPageGroup(oldPage), oldPage, parentView->options());
  169. WKPageRef newPage = view->page();
  170. view->resizeTo(800, 600);
  171. WKPageUIClient otherPageUIClient = {
  172. kWKPageUIClientCurrentVersion,
  173. view,
  174. 0, // createNewPage_deprecatedForUseWithV0
  175. 0, // showPage
  176. closeOtherPage,
  177. 0, // takeFocus
  178. focus,
  179. unfocus,
  180. 0, // runJavaScriptAlert
  181. 0, // runJavaScriptConfirm
  182. 0, // runJavaScriptPrompt
  183. 0, // setStatusText
  184. 0, // mouseDidMoveOverElement_deprecatedForUseWithV0
  185. 0, // missingPluginButtonClicked
  186. 0, // didNotHandleKeyEvent
  187. 0, // didNotHandleWheelEvent
  188. 0, // toolbarsAreVisible
  189. 0, // setToolbarsAreVisible
  190. 0, // menuBarIsVisible
  191. 0, // setMenuBarIsVisible
  192. 0, // statusBarIsVisible
  193. 0, // setStatusBarIsVisible
  194. 0, // isResizable
  195. 0, // setIsResizable
  196. getWindowFrame,
  197. setWindowFrame,
  198. runBeforeUnloadConfirmPanel,
  199. 0, // didDraw
  200. 0, // pageDidScroll
  201. exceededDatabaseQuota,
  202. 0, // runOpenPanel
  203. decidePolicyForGeolocationPermissionRequest,
  204. 0, // headerHeight
  205. 0, // footerHeight
  206. 0, // drawHeader
  207. 0, // drawFooter
  208. 0, // printFrame
  209. runModal,
  210. 0, // didCompleteRubberBandForMainFrame
  211. 0, // saveDataToFileInDownloadsFolder
  212. 0, // shouldInterruptJavaScript
  213. createOtherPage,
  214. 0, // mouseDidMoveOverElement
  215. 0, // decidePolicyForNotificationPermissionRequest
  216. 0, // unavailablePluginButtonClicked_deprecatedForUseWithV1
  217. 0, // showColorPicker
  218. 0, // hideColorPicker
  219. 0, // unavailablePluginButtonClicked
  220. };
  221. WKPageSetPageUIClient(newPage, &otherPageUIClient);
  222. view->didInitializeClients();
  223. WKRetain(newPage);
  224. return newPage;
  225. }
  226. const char* TestController::libraryPathForTesting()
  227. {
  228. // FIXME: This may not be sufficient to prevent interactions/crashes
  229. // when running more than one copy of DumpRenderTree.
  230. // See https://bugs.webkit.org/show_bug.cgi?id=10906
  231. char* dumpRenderTreeTemp = getenv("DUMPRENDERTREE_TEMP");
  232. if (dumpRenderTreeTemp)
  233. return dumpRenderTreeTemp;
  234. return platformLibraryPathForTesting();
  235. }
  236. void TestController::initialize(int argc, const char* argv[])
  237. {
  238. platformInitialize();
  239. if (argc < 2) {
  240. fputs("Usage: WebKitTestRunner [options] filename [filename2..n]\n", stderr);
  241. // FIXME: Refactor option parsing to allow us to print
  242. // an auto-generated list of options.
  243. exit(1);
  244. }
  245. bool printSupportedFeatures = false;
  246. for (int i = 1; i < argc; ++i) {
  247. std::string argument(argv[i]);
  248. if (argument == "--timeout" && i + 1 < argc) {
  249. m_longTimeout = atoi(argv[++i]);
  250. // Scale up the short timeout to match.
  251. m_shortTimeout = defaultShortTimeout * m_longTimeout / defaultLongTimeout;
  252. continue;
  253. }
  254. if (argument == "--no-timeout") {
  255. m_useWaitToDumpWatchdogTimer = false;
  256. continue;
  257. }
  258. if (argument == "--no-timeout-at-all") {
  259. m_useWaitToDumpWatchdogTimer = false;
  260. m_forceNoTimeout = true;
  261. continue;
  262. }
  263. if (argument == "--verbose") {
  264. m_verbose = true;
  265. continue;
  266. }
  267. if (argument == "--gc-between-tests") {
  268. m_gcBetweenTests = true;
  269. continue;
  270. }
  271. if (argument == "--pixel-tests" || argument == "-p") {
  272. m_shouldDumpPixelsForAllTests = true;
  273. continue;
  274. }
  275. if (argument == "--print-supported-features") {
  276. printSupportedFeatures = true;
  277. break;
  278. }
  279. // Skip any other arguments that begin with '--'.
  280. if (argument.length() >= 2 && argument[0] == '-' && argument[1] == '-')
  281. continue;
  282. m_paths.push_back(argument);
  283. }
  284. if (printSupportedFeatures) {
  285. // FIXME: On Windows, DumpRenderTree uses this to expose whether it supports 3d
  286. // transforms and accelerated compositing. When we support those features, we
  287. // should match DRT's behavior.
  288. exit(0);
  289. }
  290. m_usingServerMode = (m_paths.size() == 1 && m_paths[0] == "-");
  291. if (m_usingServerMode)
  292. m_printSeparators = true;
  293. else
  294. m_printSeparators = m_paths.size() > 1;
  295. initializeInjectedBundlePath();
  296. initializeTestPluginDirectory();
  297. WKRetainPtr<WKStringRef> pageGroupIdentifier(AdoptWK, WKStringCreateWithUTF8CString("WebKitTestRunnerPageGroup"));
  298. m_pageGroup.adopt(WKPageGroupCreateWithIdentifier(pageGroupIdentifier.get()));
  299. m_context.adopt(WKContextCreateWithInjectedBundlePath(injectedBundlePath()));
  300. m_geolocationProvider = adoptPtr(new GeolocationProviderMock(m_context.get()));
  301. #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED > 1080
  302. WKContextSetUsesNetworkProcess(m_context.get(), true);
  303. WKContextSetProcessModel(m_context.get(), kWKProcessModelMultipleSecondaryProcesses);
  304. #endif
  305. if (const char* dumpRenderTreeTemp = libraryPathForTesting()) {
  306. String temporaryFolder = String::fromUTF8(dumpRenderTreeTemp);
  307. // WebCore::pathByAppendingComponent is not used here because of the namespace,
  308. // which leads us to this ugly #ifdef and file path concatenation.
  309. #if OS(WINDOWS)
  310. const char separator = '\\';
  311. #else
  312. const char separator = '/';
  313. #endif
  314. WKContextSetApplicationCacheDirectory(m_context.get(), toWK(temporaryFolder + separator + "ApplicationCache").get());
  315. WKContextSetDatabaseDirectory(m_context.get(), toWK(temporaryFolder + separator + "Databases").get());
  316. WKContextSetLocalStorageDirectory(m_context.get(), toWK(temporaryFolder + separator + "LocalStorage").get());
  317. WKContextSetDiskCacheDirectory(m_context.get(), toWK(temporaryFolder + separator + "Cache").get());
  318. WKContextSetCookieStorageDirectory(m_context.get(), toWK(temporaryFolder + separator + "Cookies").get());
  319. WKContextSetIconDatabasePath(m_context.get(), toWK(temporaryFolder + separator + "IconDatabase" + separator + "WebpageIcons.db").get());
  320. }
  321. platformInitializeContext();
  322. WKContextInjectedBundleClient injectedBundleClient = {
  323. kWKContextInjectedBundleClientCurrentVersion,
  324. this,
  325. didReceiveMessageFromInjectedBundle,
  326. didReceiveSynchronousMessageFromInjectedBundle,
  327. 0 // getInjectedBundleInitializationUserData
  328. };
  329. WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient);
  330. WKNotificationManagerRef notificationManager = WKContextGetNotificationManager(m_context.get());
  331. WKNotificationProvider notificationKit = m_webNotificationProvider.provider();
  332. WKNotificationManagerSetProvider(notificationManager, &notificationKit);
  333. if (testPluginDirectory())
  334. WKContextSetAdditionalPluginsDirectory(m_context.get(), testPluginDirectory());
  335. createWebViewWithOptions(0);
  336. }
  337. void TestController::createWebViewWithOptions(WKDictionaryRef options)
  338. {
  339. m_mainWebView = adoptPtr(new PlatformWebView(m_context.get(), m_pageGroup.get(), 0, options));
  340. WKPageUIClient pageUIClient = {
  341. kWKPageUIClientCurrentVersion,
  342. m_mainWebView.get(),
  343. 0, // createNewPage_deprecatedForUseWithV0
  344. 0, // showPage
  345. 0, // close
  346. 0, // takeFocus
  347. focus,
  348. unfocus,
  349. 0, // runJavaScriptAlert
  350. 0, // runJavaScriptConfirm
  351. 0, // runJavaScriptPrompt
  352. 0, // setStatusText
  353. 0, // mouseDidMoveOverElement_deprecatedForUseWithV0
  354. 0, // missingPluginButtonClicked
  355. 0, // didNotHandleKeyEvent
  356. 0, // didNotHandleWheelEvent
  357. 0, // toolbarsAreVisible
  358. 0, // setToolbarsAreVisible
  359. 0, // menuBarIsVisible
  360. 0, // setMenuBarIsVisible
  361. 0, // statusBarIsVisible
  362. 0, // setStatusBarIsVisible
  363. 0, // isResizable
  364. 0, // setIsResizable
  365. getWindowFrame,
  366. setWindowFrame,
  367. runBeforeUnloadConfirmPanel,
  368. 0, // didDraw
  369. 0, // pageDidScroll
  370. exceededDatabaseQuota,
  371. 0, // runOpenPanel
  372. decidePolicyForGeolocationPermissionRequest,
  373. 0, // headerHeight
  374. 0, // footerHeight
  375. 0, // drawHeader
  376. 0, // drawFooter
  377. 0, // printFrame
  378. runModal,
  379. 0, // didCompleteRubberBandForMainFrame
  380. 0, // saveDataToFileInDownloadsFolder
  381. 0, // shouldInterruptJavaScript
  382. createOtherPage,
  383. 0, // mouseDidMoveOverElement
  384. decidePolicyForNotificationPermissionRequest, // decidePolicyForNotificationPermissionRequest
  385. 0, // unavailablePluginButtonClicked_deprecatedForUseWithV1
  386. 0, // showColorPicker
  387. 0, // hideColorPicker
  388. unavailablePluginButtonClicked,
  389. };
  390. WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient);
  391. WKPageLoaderClient pageLoaderClient = {
  392. kWKPageLoaderClientCurrentVersion,
  393. this,
  394. 0, // didStartProvisionalLoadForFrame
  395. 0, // didReceiveServerRedirectForProvisionalLoadForFrame
  396. 0, // didFailProvisionalLoadWithErrorForFrame
  397. didCommitLoadForFrame,
  398. 0, // didFinishDocumentLoadForFrame
  399. didFinishLoadForFrame,
  400. 0, // didFailLoadWithErrorForFrame
  401. 0, // didSameDocumentNavigationForFrame
  402. 0, // didReceiveTitleForFrame
  403. 0, // didFirstLayoutForFrame
  404. 0, // didFirstVisuallyNonEmptyLayoutForFrame
  405. 0, // didRemoveFrameFromHierarchy
  406. 0, // didFailToInitializePlugin
  407. 0, // didDisplayInsecureContentForFrame
  408. 0, // canAuthenticateAgainstProtectionSpaceInFrame
  409. didReceiveAuthenticationChallengeInFrame, // didReceiveAuthenticationChallengeInFrame
  410. 0, // didStartProgress
  411. 0, // didChangeProgress
  412. 0, // didFinishProgress
  413. 0, // didBecomeUnresponsive
  414. 0, // didBecomeResponsive
  415. processDidCrash,
  416. 0, // didChangeBackForwardList
  417. 0, // shouldGoToBackForwardListItem
  418. 0, // didRunInsecureContentForFrame
  419. 0, // didDetectXSSForFrame
  420. 0, // didNewFirstVisuallyNonEmptyLayout
  421. 0, // willGoToBackForwardListItem
  422. 0, // interactionOccurredWhileProcessUnresponsive
  423. 0, // pluginDidFail_deprecatedForUseWithV1
  424. 0, // didReceiveIntentForFrame
  425. 0, // registerIntentServiceForFrame
  426. 0, // didLayout
  427. 0, // pluginLoadPolicy_deprecatedForUseWithV2
  428. 0, // pluginDidFail
  429. 0, // pluginLoadPolicy
  430. };
  431. WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient);
  432. WKPagePolicyClient pagePolicyClient = {
  433. kWKPagePolicyClientCurrentVersion,
  434. this,
  435. decidePolicyForNavigationAction,
  436. 0, // decidePolicyForNewWindowAction
  437. decidePolicyForResponse,
  438. 0, // unableToImplementPolicy
  439. };
  440. WKPageSetPagePolicyClient(m_mainWebView->page(), &pagePolicyClient);
  441. m_mainWebView->didInitializeClients();
  442. }
  443. void TestController::ensureViewSupportsOptions(WKDictionaryRef options)
  444. {
  445. if (m_mainWebView && !m_mainWebView->viewSupportsOptions(options)) {
  446. WKPageSetPageUIClient(m_mainWebView->page(), 0);
  447. WKPageSetPageLoaderClient(m_mainWebView->page(), 0);
  448. WKPageSetPagePolicyClient(m_mainWebView->page(), 0);
  449. WKPageClose(m_mainWebView->page());
  450. m_mainWebView = nullptr;
  451. createWebViewWithOptions(options);
  452. resetStateToConsistentValues();
  453. }
  454. }
  455. bool TestController::resetStateToConsistentValues()
  456. {
  457. m_state = Resetting;
  458. m_beforeUnloadReturnValue = true;
  459. WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("Reset"));
  460. WKRetainPtr<WKMutableDictionaryRef> resetMessageBody = adoptWK(WKMutableDictionaryCreate());
  461. WKRetainPtr<WKStringRef> shouldGCKey = adoptWK(WKStringCreateWithUTF8CString("ShouldGC"));
  462. WKRetainPtr<WKBooleanRef> shouldGCValue = adoptWK(WKBooleanCreate(m_gcBetweenTests));
  463. WKDictionaryAddItem(resetMessageBody.get(), shouldGCKey.get(), shouldGCValue.get());
  464. WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), resetMessageBody.get());
  465. WKContextSetShouldUseFontSmoothing(TestController::shared().context(), false);
  466. WKContextSetCacheModel(TestController::shared().context(), kWKCacheModelDocumentBrowser);
  467. // FIXME: This function should also ensure that there is only one page open.
  468. // Reset the EventSender for each test.
  469. #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
  470. m_eventSenderProxy = adoptPtr(new EventSenderProxy(this));
  471. #endif
  472. // Reset preferences
  473. WKPreferencesRef preferences = WKPageGroupGetPreferences(m_pageGroup.get());
  474. WKPreferencesResetTestRunnerOverrides(preferences);
  475. WKPreferencesSetOfflineWebApplicationCacheEnabled(preferences, true);
  476. WKPreferencesSetFontSmoothingLevel(preferences, kWKFontSmoothingLevelNoSubpixelAntiAliasing);
  477. WKPreferencesSetXSSAuditorEnabled(preferences, false);
  478. WKPreferencesSetWebAudioEnabled(preferences, true);
  479. WKPreferencesSetDeveloperExtrasEnabled(preferences, true);
  480. WKPreferencesSetJavaScriptExperimentsEnabled(preferences, true);
  481. WKPreferencesSetJavaScriptCanOpenWindowsAutomatically(preferences, true);
  482. WKPreferencesSetJavaScriptCanAccessClipboard(preferences, true);
  483. WKPreferencesSetDOMPasteAllowed(preferences, true);
  484. WKPreferencesSetUniversalAccessFromFileURLsAllowed(preferences, true);
  485. WKPreferencesSetFileAccessFromFileURLsAllowed(preferences, true);
  486. #if ENABLE(FULLSCREEN_API)
  487. WKPreferencesSetFullScreenEnabled(preferences, true);
  488. #endif
  489. WKPreferencesSetPageCacheEnabled(preferences, false);
  490. WKPreferencesSetAsynchronousPluginInitializationEnabled(preferences, false);
  491. WKPreferencesSetAsynchronousPluginInitializationEnabledForAllPlugins(preferences, false);
  492. WKPreferencesSetArtificialPluginInitializationDelayEnabled(preferences, false);
  493. WKPreferencesSetTabToLinksEnabled(preferences, false);
  494. WKPreferencesSetInteractiveFormValidationEnabled(preferences, true);
  495. WKPreferencesSetMockScrollbarsEnabled(preferences, true);
  496. #if !PLATFORM(QT)
  497. static WKStringRef standardFontFamily = WKStringCreateWithUTF8CString("Times");
  498. static WKStringRef cursiveFontFamily = WKStringCreateWithUTF8CString("Apple Chancery");
  499. static WKStringRef fantasyFontFamily = WKStringCreateWithUTF8CString("Papyrus");
  500. static WKStringRef fixedFontFamily = WKStringCreateWithUTF8CString("Courier");
  501. static WKStringRef pictographFontFamily = WKStringCreateWithUTF8CString("Apple Color Emoji");
  502. static WKStringRef sansSerifFontFamily = WKStringCreateWithUTF8CString("Helvetica");
  503. static WKStringRef serifFontFamily = WKStringCreateWithUTF8CString("Times");
  504. WKPreferencesSetStandardFontFamily(preferences, standardFontFamily);
  505. WKPreferencesSetCursiveFontFamily(preferences, cursiveFontFamily);
  506. WKPreferencesSetFantasyFontFamily(preferences, fantasyFontFamily);
  507. WKPreferencesSetFixedFontFamily(preferences, fixedFontFamily);
  508. WKPreferencesSetPictographFontFamily(preferences, pictographFontFamily);
  509. WKPreferencesSetSansSerifFontFamily(preferences, sansSerifFontFamily);
  510. WKPreferencesSetSerifFontFamily(preferences, serifFontFamily);
  511. #endif
  512. WKPreferencesSetScreenFontSubstitutionEnabled(preferences, true);
  513. WKPreferencesSetInspectorUsesWebKitUserInterface(preferences, true);
  514. WKPreferencesSetAsynchronousSpellCheckingEnabled(preferences, false);
  515. #if !PLATFORM(MAC)
  516. WKTextCheckerContinuousSpellCheckingEnabledStateChanged(true);
  517. #endif
  518. // in the case that a test using the chrome input field failed, be sure to clean up for the next test
  519. m_mainWebView->removeChromeInputField();
  520. m_mainWebView->focus();
  521. // Re-set to the default backing scale factor by setting the custom scale factor to 0.
  522. WKPageSetCustomBackingScaleFactor(m_mainWebView->page(), 0);
  523. #if PLATFORM(EFL)
  524. // EFL use a real window while other ports such as Qt don't.
  525. // In EFL, we need to resize the window to the original size after calls to window.resizeTo.
  526. WKRect rect = m_mainWebView->windowFrame();
  527. m_mainWebView->setWindowFrame(WKRectMake(rect.origin.x, rect.origin.y, TestController::viewWidth, TestController::viewHeight));
  528. #endif
  529. // Reset notification permissions
  530. m_webNotificationProvider.reset();
  531. // Reset Geolocation permissions.
  532. m_geolocationPermissionRequests.clear();
  533. m_isGeolocationPermissionSet = false;
  534. m_isGeolocationPermissionAllowed = false;
  535. // Reset Custom Policy Delegate.
  536. setCustomPolicyDelegate(false, false);
  537. m_workQueueManager.clearWorkQueue();
  538. m_handlesAuthenticationChallenges = false;
  539. m_authenticationUsername = String();
  540. m_authenticationPassword = String();
  541. // Reset main page back to about:blank
  542. m_doneResetting = false;
  543. WKPageLoadURL(m_mainWebView->page(), blankURL());
  544. runUntil(m_doneResetting, ShortTimeout);
  545. return m_doneResetting;
  546. }
  547. struct TestCommand {
  548. TestCommand() : shouldDumpPixels(false), timeout(0) { }
  549. std::string pathOrURL;
  550. bool shouldDumpPixels;
  551. std::string expectedPixelHash;
  552. int timeout;
  553. };
  554. class CommandTokenizer {
  555. public:
  556. explicit CommandTokenizer(const std::string& input)
  557. : m_input(input)
  558. , m_posNextSeparator(0)
  559. {
  560. pump();
  561. }
  562. bool hasNext() const;
  563. std::string next();
  564. private:
  565. void pump();
  566. static const char kSeparator = '\'';
  567. const std::string& m_input;
  568. std::string m_next;
  569. size_t m_posNextSeparator;
  570. };
  571. void CommandTokenizer::pump()
  572. {
  573. if (m_posNextSeparator == std::string::npos || m_posNextSeparator == m_input.size()) {
  574. m_next = std::string();
  575. return;
  576. }
  577. size_t start = m_posNextSeparator ? m_posNextSeparator + 1 : 0;
  578. m_posNextSeparator = m_input.find(kSeparator, start);
  579. size_t size = m_posNextSeparator == std::string::npos ? std::string::npos : m_posNextSeparator - start;
  580. m_next = std::string(m_input, start, size);
  581. }
  582. std::string CommandTokenizer::next()
  583. {
  584. ASSERT(hasNext());
  585. std::string oldNext = m_next;
  586. pump();
  587. return oldNext;
  588. }
  589. bool CommandTokenizer::hasNext() const
  590. {
  591. return !m_next.empty();
  592. }
  593. NO_RETURN static void die(const std::string& inputLine)
  594. {
  595. fprintf(stderr, "Unexpected input line: %s\n", inputLine.c_str());
  596. exit(1);
  597. }
  598. TestCommand parseInputLine(const std::string& inputLine)
  599. {
  600. TestCommand result;
  601. CommandTokenizer tokenizer(inputLine);
  602. if (!tokenizer.hasNext())
  603. die(inputLine);
  604. std::string arg = tokenizer.next();
  605. result.pathOrURL = arg;
  606. while (tokenizer.hasNext()) {
  607. arg = tokenizer.next();
  608. if (arg == std::string("--timeout")) {
  609. std::string timeoutToken = tokenizer.next();
  610. result.timeout = atoi(timeoutToken.c_str());
  611. } else if (arg == std::string("-p") || arg == std::string("--pixel-test")) {
  612. result.shouldDumpPixels = true;
  613. if (tokenizer.hasNext())
  614. result.expectedPixelHash = tokenizer.next();
  615. } else
  616. die(inputLine);
  617. }
  618. return result;
  619. }
  620. bool TestController::runTest(const char* inputLine)
  621. {
  622. TestCommand command = parseInputLine(std::string(inputLine));
  623. m_state = RunningTest;
  624. m_currentInvocation = adoptPtr(new TestInvocation(command.pathOrURL));
  625. if (command.shouldDumpPixels || m_shouldDumpPixelsForAllTests)
  626. m_currentInvocation->setIsPixelTest(command.expectedPixelHash);
  627. if (command.timeout > 0)
  628. m_currentInvocation->setCustomTimeout(command.timeout);
  629. m_currentInvocation->invoke();
  630. m_currentInvocation.clear();
  631. return true;
  632. }
  633. void TestController::runTestingServerLoop()
  634. {
  635. char filenameBuffer[2048];
  636. while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
  637. char* newLineCharacter = strchr(filenameBuffer, '\n');
  638. if (newLineCharacter)
  639. *newLineCharacter = '\0';
  640. if (strlen(filenameBuffer) == 0)
  641. continue;
  642. if (!runTest(filenameBuffer))
  643. break;
  644. }
  645. }
  646. void TestController::run()
  647. {
  648. if (!resetStateToConsistentValues()) {
  649. m_currentInvocation->dumpWebProcessUnresponsiveness();
  650. return;
  651. }
  652. if (m_usingServerMode)
  653. runTestingServerLoop();
  654. else {
  655. for (size_t i = 0; i < m_paths.size(); ++i) {
  656. if (!runTest(m_paths[i].c_str()))
  657. break;
  658. }
  659. }
  660. }
  661. void TestController::runUntil(bool& done, TimeoutDuration timeoutDuration)
  662. {
  663. double timeout = m_noTimeout;
  664. if (!m_forceNoTimeout) {
  665. switch (timeoutDuration) {
  666. case ShortTimeout:
  667. timeout = m_shortTimeout;
  668. break;
  669. case LongTimeout:
  670. timeout = m_longTimeout;
  671. break;
  672. case CustomTimeout:
  673. timeout = m_timeout;
  674. break;
  675. case NoTimeout:
  676. default:
  677. timeout = m_noTimeout;
  678. break;
  679. }
  680. }
  681. platformRunUntil(done, timeout);
  682. }
  683. // WKContextInjectedBundleClient
  684. void TestController::didReceiveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
  685. {
  686. static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveMessageFromInjectedBundle(messageName, messageBody);
  687. }
  688. void TestController::didReceiveSynchronousMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnData, const void* clientInfo)
  689. {
  690. *returnData = static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody).leakRef();
  691. }
  692. void TestController::didReceiveKeyDownMessageFromInjectedBundle(WKDictionaryRef messageBodyDictionary, bool synchronous)
  693. {
  694. #if !PLATFORM(MANX)
  695. WKRetainPtr<WKStringRef> keyKey = adoptWK(WKStringCreateWithUTF8CString("Key"));
  696. WKStringRef key = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, keyKey.get()));
  697. WKRetainPtr<WKStringRef> modifiersKey = adoptWK(WKStringCreateWithUTF8CString("Modifiers"));
  698. WKEventModifiers modifiers = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifiersKey.get()))));
  699. WKRetainPtr<WKStringRef> locationKey = adoptWK(WKStringCreateWithUTF8CString("Location"));
  700. unsigned location = static_cast<unsigned>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, locationKey.get()))));
  701. if (synchronous)
  702. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
  703. m_eventSenderProxy->keyDown(key, modifiers, location);
  704. if (synchronous)
  705. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
  706. #endif
  707. }
  708. void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
  709. {
  710. #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
  711. if (WKStringIsEqualToUTF8CString(messageName, "EventSender")) {
  712. ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
  713. WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
  714. WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage"));
  715. WKStringRef subMessageName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, subMessageKey.get()));
  716. if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown") || WKStringIsEqualToUTF8CString(subMessageName, "MouseUp")) {
  717. WKRetainPtr<WKStringRef> buttonKey = adoptWK(WKStringCreateWithUTF8CString("Button"));
  718. unsigned button = static_cast<unsigned>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, buttonKey.get()))));
  719. WKRetainPtr<WKStringRef> modifiersKey = adoptWK(WKStringCreateWithUTF8CString("Modifiers"));
  720. WKEventModifiers modifiers = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifiersKey.get()))));
  721. // Forward to WebProcess
  722. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
  723. if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown"))
  724. m_eventSenderProxy->mouseDown(button, modifiers);
  725. else
  726. m_eventSenderProxy->mouseUp(button, modifiers);
  727. return;
  728. }
  729. if (WKStringIsEqualToUTF8CString(subMessageName, "KeyDown")) {
  730. didReceiveKeyDownMessageFromInjectedBundle(messageBodyDictionary, false);
  731. return;
  732. }
  733. ASSERT_NOT_REACHED();
  734. }
  735. #endif
  736. if (!m_currentInvocation)
  737. return;
  738. m_currentInvocation->didReceiveMessageFromInjectedBundle(messageName, messageBody);
  739. }
  740. WKRetainPtr<WKTypeRef> TestController::didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
  741. {
  742. #if PLATFORM(MAC) || PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
  743. if (WKStringIsEqualToUTF8CString(messageName, "EventSender")) {
  744. ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
  745. WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
  746. WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage"));
  747. WKStringRef subMessageName = static_cast<WKStringRef>(WKDictionaryGetItemForKey(messageBodyDictionary, subMessageKey.get()));
  748. if (WKStringIsEqualToUTF8CString(subMessageName, "KeyDown")) {
  749. didReceiveKeyDownMessageFromInjectedBundle(messageBodyDictionary, true);
  750. return 0;
  751. }
  752. if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown") || WKStringIsEqualToUTF8CString(subMessageName, "MouseUp")) {
  753. WKRetainPtr<WKStringRef> buttonKey = adoptWK(WKStringCreateWithUTF8CString("Button"));
  754. unsigned button = static_cast<unsigned>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, buttonKey.get()))));
  755. WKRetainPtr<WKStringRef> modifiersKey = adoptWK(WKStringCreateWithUTF8CString("Modifiers"));
  756. WKEventModifiers modifiers = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifiersKey.get()))));
  757. // Forward to WebProcess
  758. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
  759. if (WKStringIsEqualToUTF8CString(subMessageName, "MouseDown"))
  760. m_eventSenderProxy->mouseDown(button, modifiers);
  761. else
  762. m_eventSenderProxy->mouseUp(button, modifiers);
  763. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
  764. return 0;
  765. }
  766. if (WKStringIsEqualToUTF8CString(subMessageName, "MouseMoveTo")) {
  767. WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
  768. double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
  769. WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
  770. double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
  771. // Forward to WebProcess
  772. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
  773. m_eventSenderProxy->mouseMoveTo(x, y);
  774. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
  775. return 0;
  776. }
  777. if (WKStringIsEqualToUTF8CString(subMessageName, "MouseScrollBy")) {
  778. WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
  779. double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
  780. WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
  781. double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
  782. // Forward to WebProcess
  783. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
  784. m_eventSenderProxy->mouseScrollBy(x, y);
  785. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
  786. return 0;
  787. }
  788. if (WKStringIsEqualToUTF8CString(subMessageName, "ContinuousMouseScrollBy")) {
  789. WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
  790. double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
  791. WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
  792. double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
  793. WKRetainPtr<WKStringRef> pagedKey = adoptWK(WKStringCreateWithUTF8CString("Paged"));
  794. bool paged = static_cast<bool>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, pagedKey.get()))));
  795. // Forward to WebProcess
  796. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
  797. m_eventSenderProxy->continuousMouseScrollBy(x, y, paged);
  798. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
  799. return 0;
  800. }
  801. if (WKStringIsEqualToUTF8CString(subMessageName, "LeapForward")) {
  802. WKRetainPtr<WKStringRef> timeKey = adoptWK(WKStringCreateWithUTF8CString("TimeInMilliseconds"));
  803. unsigned time = static_cast<unsigned>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, timeKey.get()))));
  804. m_eventSenderProxy->leapForward(time);
  805. return 0;
  806. }
  807. #if ENABLE(TOUCH_EVENTS)
  808. if (WKStringIsEqualToUTF8CString(subMessageName, "AddTouchPoint")) {
  809. WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
  810. int x = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get()))));
  811. WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
  812. int y = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get()))));
  813. m_eventSenderProxy->addTouchPoint(x, y);
  814. return 0;
  815. }
  816. if (WKStringIsEqualToUTF8CString(subMessageName, "UpdateTouchPoint")) {
  817. WKRetainPtr<WKStringRef> indexKey = adoptWK(WKStringCreateWithUTF8CString("Index"));
  818. int index = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, indexKey.get()))));
  819. WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
  820. int x = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get()))));
  821. WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
  822. int y = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get()))));
  823. m_eventSenderProxy->updateTouchPoint(index, x, y);
  824. return 0;
  825. }
  826. if (WKStringIsEqualToUTF8CString(subMessageName, "SetTouchModifier")) {
  827. WKRetainPtr<WKStringRef> modifierKey = adoptWK(WKStringCreateWithUTF8CString("Modifier"));
  828. WKEventModifiers modifier = static_cast<WKEventModifiers>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, modifierKey.get()))));
  829. WKRetainPtr<WKStringRef> enableKey = adoptWK(WKStringCreateWithUTF8CString("Enable"));
  830. bool enable = static_cast<bool>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, enableKey.get()))));
  831. m_eventSenderProxy->setTouchModifier(modifier, enable);
  832. return 0;
  833. }
  834. if (WKStringIsEqualToUTF8CString(subMessageName, "SetTouchPointRadius")) {
  835. WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("RadiusX"));
  836. int x = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get()))));
  837. WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("RadiusY"));
  838. int y = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get()))));
  839. m_eventSenderProxy->setTouchPointRadius(x, y);
  840. return 0;
  841. }
  842. if (WKStringIsEqualToUTF8CString(subMessageName, "TouchStart")) {
  843. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
  844. m_eventSenderProxy->touchStart();
  845. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
  846. return 0;
  847. }
  848. if (WKStringIsEqualToUTF8CString(subMessageName, "TouchMove")) {
  849. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
  850. m_eventSenderProxy->touchMove();
  851. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
  852. return 0;
  853. }
  854. if (WKStringIsEqualToUTF8CString(subMessageName, "TouchEnd")) {
  855. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
  856. m_eventSenderProxy->touchEnd();
  857. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
  858. return 0;
  859. }
  860. if (WKStringIsEqualToUTF8CString(subMessageName, "TouchCancel")) {
  861. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), true);
  862. m_eventSenderProxy->touchCancel();
  863. WKPageSetShouldSendEventsSynchronously(mainWebView()->page(), false);
  864. return 0;
  865. }
  866. if (WKStringIsEqualToUTF8CString(subMessageName, "ClearTouchPoints")) {
  867. m_eventSenderProxy->clearTouchPoints();
  868. return 0;
  869. }
  870. if (WKStringIsEqualToUTF8CString(subMessageName, "ReleaseTouchPoint")) {
  871. WKRetainPtr<WKStringRef> indexKey = adoptWK(WKStringCreateWithUTF8CString("Index"));
  872. int index = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, indexKey.get()))));
  873. m_eventSenderProxy->releaseTouchPoint(index);
  874. return 0;
  875. }
  876. if (WKStringIsEqualToUTF8CString(subMessageName, "CancelTouchPoint")) {
  877. WKRetainPtr<WKStringRef> indexKey = adoptWK(WKStringCreateWithUTF8CString("Index"));
  878. int index = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, indexKey.get()))));
  879. m_eventSenderProxy->cancelTouchPoint(index);
  880. return 0;
  881. }
  882. #endif
  883. ASSERT_NOT_REACHED();
  884. }
  885. #endif
  886. return m_currentInvocation->didReceiveSynchronousMessageFromInjectedBundle(messageName, messageBody);
  887. }
  888. // WKPageLoaderClient
  889. void TestController::didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void* clientInfo)
  890. {
  891. static_cast<TestController*>(const_cast<void*>(clientInfo))->didCommitLoadForFrame(page, frame);
  892. }
  893. void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void* clientInfo)
  894. {
  895. static_cast<TestController*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(page, frame);
  896. }
  897. void TestController::didReceiveAuthenticationChallengeInFrame(WKPageRef page, WKFrameRef frame, WKAuthenticationChallengeRef authenticationChallenge, const void *clientInfo)
  898. {
  899. static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveAuthenticationChallengeInFrame(page, frame, authenticationChallenge);
  900. }
  901. void TestController::processDidCrash(WKPageRef page, const void* clientInfo)
  902. {
  903. static_cast<TestController*>(const_cast<void*>(clientInfo))->processDidCrash();
  904. }
  905. void TestController::didCommitLoadForFrame(WKPageRef page, WKFrameRef frame)
  906. {
  907. if (!WKFrameIsMainFrame(frame))
  908. return;
  909. mainWebView()->focus();
  910. }
  911. void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame)
  912. {
  913. if (m_state != Resetting)
  914. return;
  915. if (!WKFrameIsMainFrame(frame))
  916. return;
  917. WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKFrameCopyURL(frame));
  918. if (!WKURLIsEqual(wkURL.get(), blankURL()))
  919. return;
  920. m_doneResetting = true;
  921. shared().notifyDone();
  922. }
  923. void TestController::didReceiveAuthenticationChallengeInFrame(WKPageRef page, WKFrameRef frame, WKAuthenticationChallengeRef authenticationChallenge)
  924. {
  925. String message;
  926. if (!m_handlesAuthenticationChallenges)
  927. message = "<unknown> - didReceiveAuthenticationChallenge - Simulating cancelled authentication sheet\n";
  928. else
  929. message = String::format("<unknown> - didReceiveAuthenticationChallenge - Responding with %s:%s\n", m_authenticationUsername.utf8().data(), m_authenticationPassword.utf8().data());
  930. m_currentInvocation->outputText(message);
  931. WKAuthenticationDecisionListenerRef decisionListener = WKAuthenticationChallengeGetDecisionListener(authenticationChallenge);
  932. if (!m_handlesAuthenticationChallenges) {
  933. WKAuthenticationDecisionListenerUseCredential(decisionListener, 0);
  934. return;
  935. }
  936. WKRetainPtr<WKStringRef> username(AdoptWK, WKStringCreateWithUTF8CString(m_authenticationUsername.utf8().data()));
  937. WKRetainPtr<WKStringRef> password(AdoptWK, WKStringCreateWithUTF8CString(m_authenticationPassword.utf8().data()));
  938. WKRetainPtr<WKCredentialRef> credential(AdoptWK, WKCredentialCreate(username.get(), password.get(), kWKCredentialPersistenceForSession));
  939. WKAuthenticationDecisionListenerUseCredential(decisionListener, credential.get());
  940. }
  941. void TestController::processDidCrash()
  942. {
  943. // This function can be called multiple times when crash logs are being saved on Windows, so
  944. // ensure we only print the crashed message once.
  945. if (!m_didPrintWebProcessCrashedMessage) {
  946. #if PLATFORM(MAC)
  947. pid_t pid = WKPageGetProcessIdentifier(m_mainWebView->page());
  948. fprintf(stderr, "#CRASHED - WebProcess (pid %ld)\n", static_cast<long>(pid));
  949. #else
  950. fputs("#CRASHED - WebProcess\n", stderr);
  951. #endif
  952. fflush(stderr);
  953. m_didPrintWebProcessCrashedMessage = true;
  954. }
  955. if (m_shouldExitWhenWebProcessCrashes)
  956. exit(1);
  957. }
  958. void TestController::simulateWebNotificationClick(uint64_t notificationID)
  959. {
  960. m_webNotificationProvider.simulateWebNotificationClick(notificationID);
  961. }
  962. void TestController::setGeolocationPermission(bool enabled)
  963. {
  964. m_isGeolocationPermissionSet = true;
  965. m_isGeolocationPermissionAllowed = enabled;
  966. decidePolicyForGeolocationPermissionRequestIfPossible();
  967. }
  968. void TestController::setMockGeolocationPosition(double latitude, double longitude, double accuracy, bool providesAltitude, double altitude, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed)
  969. {
  970. m_geolocationProvider->setPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed);
  971. }
  972. void TestController::setMockGeolocationPositionUnavailableError(WKStringRef errorMessage)
  973. {
  974. m_geolocationProvider->setPositionUnavailableError(errorMessage);
  975. }
  976. void TestController::handleGeolocationPermissionRequest(WKGeolocationPermissionRequestRef geolocationPermissionRequest)
  977. {
  978. m_geolocationPermissionRequests.append(geolocationPermissionRequest);
  979. decidePolicyForGeolocationPermissionRequestIfPossible();
  980. }
  981. void TestController::setCustomPolicyDelegate(bool enabled, bool permissive)
  982. {
  983. m_policyDelegateEnabled = enabled;
  984. m_policyDelegatePermissive = permissive;
  985. }
  986. void TestController::setVisibilityState(WKPageVisibilityState visibilityState, bool isInitialState)
  987. {
  988. WKPageSetVisibilityState(m_mainWebView->page(), visibilityState, isInitialState);
  989. }
  990. void TestController::decidePolicyForGeolocationPermissionRequestIfPossible()
  991. {
  992. if (!m_isGeolocationPermissionSet)
  993. return;
  994. for (size_t i = 0; i < m_geolocationPermissionRequests.size(); ++i) {
  995. WKGeolocationPermissionRequestRef permissionRequest = m_geolocationPermissionRequests[i].get();
  996. if (m_isGeolocationPermissionAllowed)
  997. WKGeolocationPermissionRequestAllow(permissionRequest);
  998. else
  999. WKGeolocationPermissionRequestDeny(permissionRequest);
  1000. }
  1001. m_geolocationPermissionRequests.clear();
  1002. }
  1003. void TestController::decidePolicyForNotificationPermissionRequest(WKPageRef page, WKSecurityOriginRef origin, WKNotificationPermissionRequestRef request, const void*)
  1004. {
  1005. TestController::shared().decidePolicyForNotificationPermissionRequest(page, origin, request);
  1006. }
  1007. void TestController::decidePolicyForNotificationPermissionRequest(WKPageRef, WKSecurityOriginRef, WKNotificationPermissionRequestRef request)
  1008. {
  1009. WKNotificationPermissionRequestAllow(request);
  1010. }
  1011. void TestController::unavailablePluginButtonClicked(WKPageRef, WKPluginUnavailabilityReason, WKDictionaryRef, const void*)
  1012. {
  1013. printf("MISSING PLUGIN BUTTON PRESSED\n");
  1014. }
  1015. void TestController::decidePolicyForNavigationAction(WKPageRef, WKFrameRef, WKFrameNavigationType, WKEventModifiers, WKEventMouseButton, WKURLRequestRef, WKFramePolicyListenerRef listener, WKTypeRef, const void* clientInfo)
  1016. {
  1017. static_cast<TestController*>(const_cast<void*>(clientInfo))->decidePolicyForNavigationAction(listener);
  1018. }
  1019. void TestController::decidePolicyForNavigationAction(WKFramePolicyListenerRef listener)
  1020. {
  1021. if (m_policyDelegateEnabled && !m_policyDelegatePermissive) {
  1022. WKFramePolicyListenerIgnore(listener);
  1023. return;
  1024. }
  1025. WKFramePolicyListenerUse(listener);
  1026. }
  1027. void TestController::decidePolicyForResponse(WKPageRef, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef, WKFramePolicyListenerRef listener, WKTypeRef, const void* clientInfo)
  1028. {
  1029. static_cast<TestController*>(const_cast<void*>(clientInfo))->decidePolicyForResponse(frame, response, listener);
  1030. }
  1031. void TestController::decidePolicyForResponse(WKFrameRef frame, WKURLResponseRef response, WKFramePolicyListenerRef listener)
  1032. {
  1033. // Even though Response was already checked by WKBundlePagePolicyClient, the check did not include plugins
  1034. // so we have to re-check again.
  1035. WKRetainPtr<WKStringRef> wkMIMEType(AdoptWK, WKURLResponseCopyMIMEType(response));
  1036. if (WKFrameCanShowMIMEType(frame, wkMIMEType.get())) {
  1037. WKFramePolicyListenerUse(listener);
  1038. return;
  1039. }
  1040. WKFramePolicyListenerIgnore(listener);
  1041. }
  1042. } // namespace WTR