TestInvocation.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. /*
  2. * Copyright (C) 2010, 2011, 2012 Apple Inc. All rights reserved.
  3. * Copyright (C) 2012 Intel Corporation. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
  15. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  16. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
  18. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  24. * THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "config.h"
  27. #include "TestInvocation.h"
  28. #include "PlatformWebView.h"
  29. #include "StringFunctions.h"
  30. #include "TestController.h"
  31. #include <climits>
  32. #include <cstdio>
  33. #include <WebKit2/WKContextPrivate.h>
  34. #include <WebKit2/WKData.h>
  35. #include <WebKit2/WKDictionary.h>
  36. #include <WebKit2/WKInspector.h>
  37. #include <WebKit2/WKRetainPtr.h>
  38. #include <wtf/OwnArrayPtr.h>
  39. #include <wtf/PassOwnArrayPtr.h>
  40. #include <wtf/PassOwnPtr.h>
  41. #include <wtf/text/CString.h>
  42. #if PLATFORM(MAC)
  43. #include <Carbon/Carbon.h>
  44. #include <WebKit2/WKPagePrivateMac.h>
  45. #endif
  46. #if OS(WINDOWS)
  47. #include <direct.h> // For _getcwd.
  48. #define getcwd _getcwd // MSDN says getcwd is deprecated.
  49. #define PATH_MAX _MAX_PATH
  50. #else
  51. #include <unistd.h> // For getcwd.
  52. #endif
  53. using namespace WebKit;
  54. using namespace std;
  55. namespace WTR {
  56. static WKURLRef createWKURL(const char* pathOrURL)
  57. {
  58. if (strstr(pathOrURL, "http://") || strstr(pathOrURL, "https://") || strstr(pathOrURL, "file://"))
  59. return WKURLCreateWithUTF8CString(pathOrURL);
  60. // Creating from filesytem path.
  61. size_t length = strlen(pathOrURL);
  62. if (!length)
  63. return 0;
  64. #if OS(WINDOWS)
  65. const char separator = '\\';
  66. bool isAbsolutePath = length >= 3 && pathOrURL[1] == ':' && pathOrURL[2] == separator;
  67. // FIXME: Remove the "localhost/" suffix once <http://webkit.org/b/55683> is fixed.
  68. const char* filePrefix = "file://localhost/";
  69. #else
  70. const char separator = '/';
  71. bool isAbsolutePath = pathOrURL[0] == separator;
  72. const char* filePrefix = "file://";
  73. #endif
  74. static const size_t prefixLength = strlen(filePrefix);
  75. OwnArrayPtr<char> buffer;
  76. if (isAbsolutePath) {
  77. buffer = adoptArrayPtr(new char[prefixLength + length + 1]);
  78. strcpy(buffer.get(), filePrefix);
  79. strcpy(buffer.get() + prefixLength, pathOrURL);
  80. } else {
  81. buffer = adoptArrayPtr(new char[prefixLength + PATH_MAX + length + 2]); // 1 for the separator
  82. strcpy(buffer.get(), filePrefix);
  83. if (!getcwd(buffer.get() + prefixLength, PATH_MAX))
  84. return 0;
  85. size_t numCharacters = strlen(buffer.get());
  86. buffer[numCharacters] = separator;
  87. strcpy(buffer.get() + numCharacters + 1, pathOrURL);
  88. }
  89. return WKURLCreateWithUTF8CString(buffer.get());
  90. }
  91. TestInvocation::TestInvocation(const std::string& pathOrURL)
  92. : m_url(AdoptWK, createWKURL(pathOrURL.c_str()))
  93. , m_pathOrURL(pathOrURL)
  94. , m_dumpPixels(false)
  95. , m_timeout(0)
  96. , m_gotInitialResponse(false)
  97. , m_gotFinalMessage(false)
  98. , m_gotRepaint(false)
  99. , m_error(false)
  100. , m_webProcessIsUnresponsive(false)
  101. {
  102. }
  103. TestInvocation::~TestInvocation()
  104. {
  105. }
  106. void TestInvocation::setIsPixelTest(const std::string& expectedPixelHash)
  107. {
  108. m_dumpPixels = true;
  109. m_expectedPixelHash = expectedPixelHash;
  110. }
  111. void TestInvocation::setCustomTimeout(int timeout)
  112. {
  113. m_timeout = timeout;
  114. }
  115. static void sizeWebViewForCurrentTest(const char* pathOrURL)
  116. {
  117. bool isSVGW3CTest = strstr(pathOrURL, "svg/W3C-SVG-1.1") || strstr(pathOrURL, "svg\\W3C-SVG-1.1");
  118. if (isSVGW3CTest)
  119. TestController::shared().mainWebView()->resizeTo(TestController::w3cSVGViewWidth, TestController::w3cSVGViewHeight);
  120. else
  121. TestController::shared().mainWebView()->resizeTo(TestController::viewWidth, TestController::viewHeight);
  122. }
  123. static bool shouldLogFrameLoadDelegates(const char* pathOrURL)
  124. {
  125. return strstr(pathOrURL, "loading/");
  126. }
  127. #if ENABLE(INSPECTOR)
  128. static bool shouldOpenWebInspector(const char* pathOrURL)
  129. {
  130. return strstr(pathOrURL, "inspector/") || strstr(pathOrURL, "inspector\\");
  131. }
  132. #endif
  133. #if PLATFORM(MAC)
  134. static bool shouldUseTiledDrawing(const char* pathOrURL)
  135. {
  136. return strstr(pathOrURL, "tiled-drawing/") || strstr(pathOrURL, "tiled-drawing\\");
  137. }
  138. #endif
  139. static void updateTiledDrawingForCurrentTest(const char* pathOrURL)
  140. {
  141. #if PLATFORM(MAC)
  142. WKRetainPtr<WKMutableDictionaryRef> viewOptions = adoptWK(WKMutableDictionaryCreate());
  143. WKRetainPtr<WKStringRef> useTiledDrawingKey = adoptWK(WKStringCreateWithUTF8CString("TiledDrawing"));
  144. WKRetainPtr<WKBooleanRef> useTiledDrawingValue = adoptWK(WKBooleanCreate(shouldUseTiledDrawing(pathOrURL)));
  145. WKDictionaryAddItem(viewOptions.get(), useTiledDrawingKey.get(), useTiledDrawingValue.get());
  146. TestController::shared().ensureViewSupportsOptions(viewOptions.get());
  147. #else
  148. UNUSED_PARAM(pathOrURL);
  149. #endif
  150. }
  151. static bool shouldUseFixedLayout(const char* pathOrURL)
  152. {
  153. #if ENABLE(CSS_DEVICE_ADAPTATION)
  154. if (strstr(pathOrURL, "device-adapt/") || strstr(pathOrURL, "device-adapt\\"))
  155. return true;
  156. #endif
  157. #if USE(TILED_BACKING_STORE) && PLATFORM(EFL)
  158. if (strstr(pathOrURL, "sticky/") || strstr(pathOrURL, "sticky\\"))
  159. return true;
  160. #endif
  161. return false;
  162. UNUSED_PARAM(pathOrURL);
  163. }
  164. static void updateLayoutType(const char* pathOrURL)
  165. {
  166. WKRetainPtr<WKMutableDictionaryRef> viewOptions = adoptWK(WKMutableDictionaryCreate());
  167. WKRetainPtr<WKStringRef> useFixedLayoutKey = adoptWK(WKStringCreateWithUTF8CString("UseFixedLayout"));
  168. WKRetainPtr<WKBooleanRef> useFixedLayoutValue = adoptWK(WKBooleanCreate(shouldUseFixedLayout(pathOrURL)));
  169. WKDictionaryAddItem(viewOptions.get(), useFixedLayoutKey.get(), useFixedLayoutValue.get());
  170. TestController::shared().ensureViewSupportsOptions(viewOptions.get());
  171. }
  172. void TestInvocation::invoke()
  173. {
  174. TestController::TimeoutDuration timeoutToUse = TestController::LongTimeout;
  175. sizeWebViewForCurrentTest(m_pathOrURL.c_str());
  176. updateLayoutType(m_pathOrURL.c_str());
  177. updateTiledDrawingForCurrentTest(m_pathOrURL.c_str());
  178. m_textOutput.clear();
  179. WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("BeginTest"));
  180. WKRetainPtr<WKMutableDictionaryRef> beginTestMessageBody = adoptWK(WKMutableDictionaryCreate());
  181. WKRetainPtr<WKStringRef> dumpFrameLoadDelegatesKey = adoptWK(WKStringCreateWithUTF8CString("DumpFrameLoadDelegates"));
  182. WKRetainPtr<WKBooleanRef> dumpFrameLoadDelegatesValue = adoptWK(WKBooleanCreate(shouldLogFrameLoadDelegates(m_pathOrURL.c_str())));
  183. WKDictionaryAddItem(beginTestMessageBody.get(), dumpFrameLoadDelegatesKey.get(), dumpFrameLoadDelegatesValue.get());
  184. WKRetainPtr<WKStringRef> dumpPixelsKey = adoptWK(WKStringCreateWithUTF8CString("DumpPixels"));
  185. WKRetainPtr<WKBooleanRef> dumpPixelsValue = adoptWK(WKBooleanCreate(m_dumpPixels));
  186. WKDictionaryAddItem(beginTestMessageBody.get(), dumpPixelsKey.get(), dumpPixelsValue.get());
  187. WKRetainPtr<WKStringRef> useWaitToDumpWatchdogTimerKey = adoptWK(WKStringCreateWithUTF8CString("UseWaitToDumpWatchdogTimer"));
  188. WKRetainPtr<WKBooleanRef> useWaitToDumpWatchdogTimerValue = adoptWK(WKBooleanCreate(TestController::shared().useWaitToDumpWatchdogTimer()));
  189. WKDictionaryAddItem(beginTestMessageBody.get(), useWaitToDumpWatchdogTimerKey.get(), useWaitToDumpWatchdogTimerValue.get());
  190. WKRetainPtr<WKStringRef> timeoutKey = adoptWK(WKStringCreateWithUTF8CString("Timeout"));
  191. WKRetainPtr<WKUInt64Ref> timeoutValue = adoptWK(WKUInt64Create(m_timeout));
  192. WKDictionaryAddItem(beginTestMessageBody.get(), timeoutKey.get(), timeoutValue.get());
  193. WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), beginTestMessageBody.get());
  194. TestController::shared().runUntil(m_gotInitialResponse, TestController::ShortTimeout);
  195. if (!m_gotInitialResponse) {
  196. m_errorMessage = "Timed out waiting for initial response from web process\n";
  197. m_webProcessIsUnresponsive = true;
  198. goto end;
  199. }
  200. if (m_error)
  201. goto end;
  202. #if ENABLE(INSPECTOR)
  203. if (shouldOpenWebInspector(m_pathOrURL.c_str()))
  204. WKInspectorShow(WKPageGetInspector(TestController::shared().mainWebView()->page()));
  205. #endif // ENABLE(INSPECTOR)
  206. WKPageLoadURL(TestController::shared().mainWebView()->page(), m_url.get());
  207. if (TestController::shared().useWaitToDumpWatchdogTimer()) {
  208. if (m_timeout > 0)
  209. timeoutToUse = TestController::CustomTimeout;
  210. } else
  211. timeoutToUse = TestController::NoTimeout;
  212. TestController::shared().runUntil(m_gotFinalMessage, timeoutToUse);
  213. if (!m_gotFinalMessage) {
  214. m_errorMessage = "Timed out waiting for final message from web process\n";
  215. m_webProcessIsUnresponsive = true;
  216. goto end;
  217. }
  218. if (m_error)
  219. goto end;
  220. dumpResults();
  221. end:
  222. #if ENABLE(INSPECTOR)
  223. if (m_gotInitialResponse)
  224. WKInspectorClose(WKPageGetInspector(TestController::shared().mainWebView()->page()));
  225. #endif // ENABLE(INSPECTOR)
  226. if (m_webProcessIsUnresponsive)
  227. dumpWebProcessUnresponsiveness();
  228. else if (!TestController::shared().resetStateToConsistentValues()) {
  229. m_errorMessage = "Timed out loading about:blank before the next test";
  230. dumpWebProcessUnresponsiveness();
  231. }
  232. }
  233. void TestInvocation::dumpWebProcessUnresponsiveness()
  234. {
  235. const char* errorMessageToStderr = 0;
  236. #if PLATFORM(MAC)
  237. char buffer[64];
  238. pid_t pid = WKPageGetProcessIdentifier(TestController::shared().mainWebView()->page());
  239. sprintf(buffer, "#PROCESS UNRESPONSIVE - WebProcess (pid %ld)\n", static_cast<long>(pid));
  240. errorMessageToStderr = buffer;
  241. #else
  242. errorMessageToStderr = "#PROCESS UNRESPONSIVE - WebProcess";
  243. #endif
  244. dump(m_errorMessage.c_str(), errorMessageToStderr, true);
  245. }
  246. void TestInvocation::dump(const char* textToStdout, const char* textToStderr, bool seenError)
  247. {
  248. printf("Content-Type: text/plain\n");
  249. if (textToStdout)
  250. fputs(textToStdout, stdout);
  251. if (textToStderr)
  252. fputs(textToStderr, stderr);
  253. fputs("#EOF\n", stdout);
  254. fputs("#EOF\n", stderr);
  255. if (seenError)
  256. fputs("#EOF\n", stdout);
  257. fflush(stdout);
  258. fflush(stderr);
  259. }
  260. void TestInvocation::dumpResults()
  261. {
  262. if (m_textOutput.length() || !m_audioResult)
  263. dump(m_textOutput.toString().utf8().data());
  264. else
  265. dumpAudio(m_audioResult.get());
  266. if (m_dumpPixels && m_pixelResult)
  267. dumpPixelsAndCompareWithExpected(m_pixelResult.get(), m_repaintRects.get());
  268. fputs("#EOF\n", stdout);
  269. fflush(stdout);
  270. fflush(stderr);
  271. }
  272. void TestInvocation::dumpAudio(WKDataRef audioData)
  273. {
  274. size_t length = WKDataGetSize(audioData);
  275. if (!length)
  276. return;
  277. const unsigned char* data = WKDataGetBytes(audioData);
  278. printf("Content-Type: audio/wav\n");
  279. printf("Content-Length: %lu\n", static_cast<unsigned long>(length));
  280. const size_t bytesToWriteInOneChunk = 1 << 15;
  281. size_t dataRemainingToWrite = length;
  282. while (dataRemainingToWrite) {
  283. size_t bytesToWriteInThisChunk = std::min(dataRemainingToWrite, bytesToWriteInOneChunk);
  284. size_t bytesWritten = fwrite(data, 1, bytesToWriteInThisChunk, stdout);
  285. if (bytesWritten != bytesToWriteInThisChunk)
  286. break;
  287. dataRemainingToWrite -= bytesWritten;
  288. data += bytesWritten;
  289. }
  290. printf("#EOF\n");
  291. fprintf(stderr, "#EOF\n");
  292. }
  293. bool TestInvocation::compareActualHashToExpectedAndDumpResults(const char actualHash[33])
  294. {
  295. // Compute the hash of the bitmap context pixels
  296. fprintf(stdout, "\nActualHash: %s\n", actualHash);
  297. if (!m_expectedPixelHash.length())
  298. return false;
  299. ASSERT(m_expectedPixelHash.length() == 32);
  300. fprintf(stdout, "\nExpectedHash: %s\n", m_expectedPixelHash.c_str());
  301. // FIXME: Do case insensitive compare.
  302. return m_expectedPixelHash == actualHash;
  303. }
  304. void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
  305. {
  306. if (WKStringIsEqualToUTF8CString(messageName, "Error")) {
  307. // Set all states to true to stop spinning the runloop.
  308. m_gotInitialResponse = true;
  309. m_gotFinalMessage = true;
  310. m_error = true;
  311. m_errorMessage = "FAIL\n";
  312. TestController::shared().notifyDone();
  313. return;
  314. }
  315. if (WKStringIsEqualToUTF8CString(messageName, "Ack")) {
  316. ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
  317. WKStringRef messageBodyString = static_cast<WKStringRef>(messageBody);
  318. if (WKStringIsEqualToUTF8CString(messageBodyString, "BeginTest")) {
  319. m_gotInitialResponse = true;
  320. TestController::shared().notifyDone();
  321. return;
  322. }
  323. ASSERT_NOT_REACHED();
  324. }
  325. if (WKStringIsEqualToUTF8CString(messageName, "Done")) {
  326. ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
  327. WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
  328. WKRetainPtr<WKStringRef> pixelResultKey = adoptWK(WKStringCreateWithUTF8CString("PixelResult"));
  329. m_pixelResult = static_cast<WKImageRef>(WKDictionaryGetItemForKey(messageBodyDictionary, pixelResultKey.get()));
  330. ASSERT(!m_pixelResult || m_dumpPixels);
  331. WKRetainPtr<WKStringRef> repaintRectsKey = adoptWK(WKStringCreateWithUTF8CString("RepaintRects"));
  332. m_repaintRects = static_cast<WKArrayRef>(WKDictionaryGetItemForKey(messageBodyDictionary, repaintRectsKey.get()));
  333. WKRetainPtr<WKStringRef> audioResultKey = adoptWK(WKStringCreateWithUTF8CString("AudioResult"));
  334. m_audioResult = static_cast<WKDataRef>(WKDictionaryGetItemForKey(messageBodyDictionary, audioResultKey.get()));
  335. m_gotFinalMessage = true;
  336. TestController::shared().notifyDone();
  337. return;
  338. }
  339. if (WKStringIsEqualToUTF8CString(messageName, "TextOutput")) {
  340. ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
  341. WKStringRef textOutput = static_cast<WKStringRef>(messageBody);
  342. m_textOutput.append(toWTFString(textOutput));
  343. return;
  344. }
  345. if (WKStringIsEqualToUTF8CString(messageName, "BeforeUnloadReturnValue")) {
  346. ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
  347. WKBooleanRef beforeUnloadReturnValue = static_cast<WKBooleanRef>(messageBody);
  348. TestController::shared().setBeforeUnloadReturnValue(WKBooleanGetValue(beforeUnloadReturnValue));
  349. return;
  350. }
  351. if (WKStringIsEqualToUTF8CString(messageName, "AddChromeInputField")) {
  352. TestController::shared().mainWebView()->addChromeInputField();
  353. WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallAddChromeInputFieldCallback"));
  354. WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
  355. return;
  356. }
  357. if (WKStringIsEqualToUTF8CString(messageName, "RemoveChromeInputField")) {
  358. TestController::shared().mainWebView()->removeChromeInputField();
  359. WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallRemoveChromeInputFieldCallback"));
  360. WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
  361. return;
  362. }
  363. if (WKStringIsEqualToUTF8CString(messageName, "FocusWebView")) {
  364. TestController::shared().mainWebView()->makeWebViewFirstResponder();
  365. WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallFocusWebViewCallback"));
  366. WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
  367. return;
  368. }
  369. if (WKStringIsEqualToUTF8CString(messageName, "SetBackingScaleFactor")) {
  370. ASSERT(WKGetTypeID(messageBody) == WKDoubleGetTypeID());
  371. double backingScaleFactor = WKDoubleGetValue(static_cast<WKDoubleRef>(messageBody));
  372. WKPageSetCustomBackingScaleFactor(TestController::shared().mainWebView()->page(), backingScaleFactor);
  373. WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("CallSetBackingScaleFactorCallback"));
  374. WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
  375. return;
  376. }
  377. if (WKStringIsEqualToUTF8CString(messageName, "SimulateWebNotificationClick")) {
  378. ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
  379. uint64_t notificationID = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
  380. TestController::shared().simulateWebNotificationClick(notificationID);
  381. return;
  382. }
  383. if (WKStringIsEqualToUTF8CString(messageName, "SetGeolocationPermission")) {
  384. ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
  385. WKBooleanRef enabledWK = static_cast<WKBooleanRef>(messageBody);
  386. TestController::shared().setGeolocationPermission(WKBooleanGetValue(enabledWK));
  387. return;
  388. }
  389. if (WKStringIsEqualToUTF8CString(messageName, "SetMockGeolocationPosition")) {
  390. ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
  391. WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
  392. WKRetainPtr<WKStringRef> latitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("latitude"));
  393. WKDoubleRef latitudeWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, latitudeKeyWK.get()));
  394. double latitude = WKDoubleGetValue(latitudeWK);
  395. WKRetainPtr<WKStringRef> longitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("longitude"));
  396. WKDoubleRef longitudeWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, longitudeKeyWK.get()));
  397. double longitude = WKDoubleGetValue(longitudeWK);
  398. WKRetainPtr<WKStringRef> accuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("accuracy"));
  399. WKDoubleRef accuracyWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, accuracyKeyWK.get()));
  400. double accuracy = WKDoubleGetValue(accuracyWK);
  401. WKRetainPtr<WKStringRef> providesAltitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesAltitude"));
  402. WKBooleanRef providesAltitudeWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesAltitudeKeyWK.get()));
  403. bool providesAltitude = WKBooleanGetValue(providesAltitudeWK);
  404. WKRetainPtr<WKStringRef> altitudeKeyWK(AdoptWK, WKStringCreateWithUTF8CString("altitude"));
  405. WKDoubleRef altitudeWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, altitudeKeyWK.get()));
  406. double altitude = WKDoubleGetValue(altitudeWK);
  407. WKRetainPtr<WKStringRef> providesAltitudeAccuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesAltitudeAccuracy"));
  408. WKBooleanRef providesAltitudeAccuracyWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesAltitudeAccuracyKeyWK.get()));
  409. bool providesAltitudeAccuracy = WKBooleanGetValue(providesAltitudeAccuracyWK);
  410. WKRetainPtr<WKStringRef> altitudeAccuracyKeyWK(AdoptWK, WKStringCreateWithUTF8CString("altitudeAccuracy"));
  411. WKDoubleRef altitudeAccuracyWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, altitudeAccuracyKeyWK.get()));
  412. double altitudeAccuracy = WKDoubleGetValue(altitudeAccuracyWK);
  413. WKRetainPtr<WKStringRef> providesHeadingKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesHeading"));
  414. WKBooleanRef providesHeadingWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesHeadingKeyWK.get()));
  415. bool providesHeading = WKBooleanGetValue(providesHeadingWK);
  416. WKRetainPtr<WKStringRef> headingKeyWK(AdoptWK, WKStringCreateWithUTF8CString("heading"));
  417. WKDoubleRef headingWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, headingKeyWK.get()));
  418. double heading = WKDoubleGetValue(headingWK);
  419. WKRetainPtr<WKStringRef> providesSpeedKeyWK(AdoptWK, WKStringCreateWithUTF8CString("providesSpeed"));
  420. WKBooleanRef providesSpeedWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, providesSpeedKeyWK.get()));
  421. bool providesSpeed = WKBooleanGetValue(providesSpeedWK);
  422. WKRetainPtr<WKStringRef> speedKeyWK(AdoptWK, WKStringCreateWithUTF8CString("speed"));
  423. WKDoubleRef speedWK = static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, speedKeyWK.get()));
  424. double speed = WKDoubleGetValue(speedWK);
  425. TestController::shared().setMockGeolocationPosition(latitude, longitude, accuracy, providesAltitude, altitude, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed);
  426. return;
  427. }
  428. if (WKStringIsEqualToUTF8CString(messageName, "SetMockGeolocationPositionUnavailableError")) {
  429. ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
  430. WKStringRef errorMessage = static_cast<WKStringRef>(messageBody);
  431. TestController::shared().setMockGeolocationPositionUnavailableError(errorMessage);
  432. return;
  433. }
  434. if (WKStringIsEqualToUTF8CString(messageName, "SetCustomPolicyDelegate")) {
  435. ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
  436. WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
  437. WKRetainPtr<WKStringRef> enabledKeyWK(AdoptWK, WKStringCreateWithUTF8CString("enabled"));
  438. WKBooleanRef enabledWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, enabledKeyWK.get()));
  439. bool enabled = WKBooleanGetValue(enabledWK);
  440. WKRetainPtr<WKStringRef> permissiveKeyWK(AdoptWK, WKStringCreateWithUTF8CString("permissive"));
  441. WKBooleanRef permissiveWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, permissiveKeyWK.get()));
  442. bool permissive = WKBooleanGetValue(permissiveWK);
  443. TestController::shared().setCustomPolicyDelegate(enabled, permissive);
  444. return;
  445. }
  446. if (WKStringIsEqualToUTF8CString(messageName, "SetVisibilityState")) {
  447. ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
  448. WKDictionaryRef messageBodyDictionary = static_cast<WKDictionaryRef>(messageBody);
  449. WKRetainPtr<WKStringRef> visibilityStateKeyWK(AdoptWK, WKStringCreateWithUTF8CString("visibilityState"));
  450. WKUInt64Ref visibilityStateWK = static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, visibilityStateKeyWK.get()));
  451. WKPageVisibilityState visibilityState = static_cast<WKPageVisibilityState>(WKUInt64GetValue(visibilityStateWK));
  452. WKRetainPtr<WKStringRef> isInitialKeyWK(AdoptWK, WKStringCreateWithUTF8CString("isInitialState"));
  453. WKBooleanRef isInitialWK = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(messageBodyDictionary, isInitialKeyWK.get()));
  454. bool isInitialState = WKBooleanGetValue(isInitialWK);
  455. TestController::shared().setVisibilityState(visibilityState, isInitialState);
  456. return;
  457. }
  458. if (WKStringIsEqualToUTF8CString(messageName, "ProcessWorkQueue")) {
  459. if (TestController::shared().workQueueManager().processWorkQueue()) {
  460. WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("WorkQueueProcessedCallback"));
  461. WKContextPostMessageToInjectedBundle(TestController::shared().context(), messageName.get(), 0);
  462. }
  463. return;
  464. }
  465. if (WKStringIsEqualToUTF8CString(messageName, "QueueBackNavigation")) {
  466. ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
  467. uint64_t stepCount = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
  468. TestController::shared().workQueueManager().queueBackNavigation(stepCount);
  469. return;
  470. }
  471. if (WKStringIsEqualToUTF8CString(messageName, "QueueForwardNavigation")) {
  472. ASSERT(WKGetTypeID(messageBody) == WKUInt64GetTypeID());
  473. uint64_t stepCount = WKUInt64GetValue(static_cast<WKUInt64Ref>(messageBody));
  474. TestController::shared().workQueueManager().queueForwardNavigation(stepCount);
  475. return;
  476. }
  477. if (WKStringIsEqualToUTF8CString(messageName, "QueueLoad")) {
  478. ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
  479. WKDictionaryRef loadDataDictionary = static_cast<WKDictionaryRef>(messageBody);
  480. WKRetainPtr<WKStringRef> urlKey(AdoptWK, WKStringCreateWithUTF8CString("url"));
  481. WKStringRef urlWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, urlKey.get()));
  482. WKRetainPtr<WKStringRef> targetKey(AdoptWK, WKStringCreateWithUTF8CString("target"));
  483. WKStringRef targetWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, targetKey.get()));
  484. TestController::shared().workQueueManager().queueLoad(toWTFString(urlWK), toWTFString(targetWK));
  485. return;
  486. }
  487. if (WKStringIsEqualToUTF8CString(messageName, "QueueLoadHTMLString")) {
  488. ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
  489. WKDictionaryRef loadDataDictionary = static_cast<WKDictionaryRef>(messageBody);
  490. WKRetainPtr<WKStringRef> contentKey(AdoptWK, WKStringCreateWithUTF8CString("content"));
  491. WKStringRef contentWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, contentKey.get()));
  492. WKRetainPtr<WKStringRef> baseURLKey(AdoptWK, WKStringCreateWithUTF8CString("baseURL"));
  493. WKStringRef baseURLWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, baseURLKey.get()));
  494. WKRetainPtr<WKStringRef> unreachableURLKey(AdoptWK, WKStringCreateWithUTF8CString("unreachableURL"));
  495. WKStringRef unreachableURLWK = static_cast<WKStringRef>(WKDictionaryGetItemForKey(loadDataDictionary, unreachableURLKey.get()));
  496. TestController::shared().workQueueManager().queueLoadHTMLString(toWTFString(contentWK), baseURLWK ? toWTFString(baseURLWK) : String(), unreachableURLWK ? toWTFString(unreachableURLWK) : String());
  497. return;
  498. }
  499. if (WKStringIsEqualToUTF8CString(messageName, "QueueReload")) {
  500. TestController::shared().workQueueManager().queueReload();
  501. return;
  502. }
  503. if (WKStringIsEqualToUTF8CString(messageName, "QueueLoadingScript")) {
  504. ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
  505. WKStringRef script = static_cast<WKStringRef>(messageBody);
  506. TestController::shared().workQueueManager().queueLoadingScript(toWTFString(script));
  507. return;
  508. }
  509. if (WKStringIsEqualToUTF8CString(messageName, "QueueNonLoadingScript")) {
  510. ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
  511. WKStringRef script = static_cast<WKStringRef>(messageBody);
  512. TestController::shared().workQueueManager().queueNonLoadingScript(toWTFString(script));
  513. return;
  514. }
  515. if (WKStringIsEqualToUTF8CString(messageName, "SetHandlesAuthenticationChallenge")) {
  516. ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
  517. WKBooleanRef value = static_cast<WKBooleanRef>(messageBody);
  518. TestController::shared().setHandlesAuthenticationChallenges(WKBooleanGetValue(value));
  519. return;
  520. }
  521. if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationUsername")) {
  522. ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
  523. WKStringRef username = static_cast<WKStringRef>(messageBody);
  524. TestController::shared().setAuthenticationUsername(toWTFString(username));
  525. return;
  526. }
  527. if (WKStringIsEqualToUTF8CString(messageName, "SetAuthenticationPassword")) {
  528. ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
  529. WKStringRef password = static_cast<WKStringRef>(messageBody);
  530. TestController::shared().setAuthenticationPassword(toWTFString(password));
  531. return;
  532. }
  533. ASSERT_NOT_REACHED();
  534. }
  535. WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
  536. {
  537. if (WKStringIsEqualToUTF8CString(messageName, "SetWindowIsKey")) {
  538. ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
  539. WKBooleanRef isKeyValue = static_cast<WKBooleanRef>(messageBody);
  540. TestController::shared().mainWebView()->setWindowIsKey(WKBooleanGetValue(isKeyValue));
  541. return 0;
  542. }
  543. if (WKStringIsEqualToUTF8CString(messageName, "IsWorkQueueEmpty")) {
  544. bool isEmpty = TestController::shared().workQueueManager().isWorkQueueEmpty();
  545. WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(isEmpty));
  546. return result;
  547. }
  548. if (WKStringIsEqualToUTF8CString(messageName, "SecureEventInputIsEnabled")) {
  549. #if PLATFORM(MAC)
  550. WKRetainPtr<WKBooleanRef> result(AdoptWK, WKBooleanCreate(IsSecureEventInputEnabled()));
  551. #else
  552. WKRetainPtr<WKBooleanRef> result(AdoptWK, WKBooleanCreate(false));
  553. #endif
  554. return result;
  555. }
  556. ASSERT_NOT_REACHED();
  557. return 0;
  558. }
  559. void TestInvocation::outputText(const WTF::String& text)
  560. {
  561. m_textOutput.append(text);
  562. }
  563. } // namespace WTR