WKContextRef createContextForInjectedBundleTest(const std::string& testName, WKTypeRef userData) { WKRetainPtr<WKStringRef> injectedBundlePath(AdoptWK, createInjectedBundlePath()); WKContextRef context = WKContextCreateWithInjectedBundlePath(injectedBundlePath.get()); WKRetainPtr<WKMutableDictionaryRef> initializationDictionary(AdoptWK, WKMutableDictionaryCreate()); WKRetainPtr<WKStringRef> testNameKey(AdoptWK, WKStringCreateWithUTF8CString("TestName")); WKRetainPtr<WKStringRef> testNameString(AdoptWK, WKStringCreateWithUTF8CString(testName.c_str())); WKDictionaryAddItem(initializationDictionary.get(), testNameKey.get(), testNameString.get()); WKRetainPtr<WKStringRef> userDataKey(AdoptWK, WKStringCreateWithUTF8CString("UserData")); WKDictionaryAddItem(initializationDictionary.get(), userDataKey.get(), userData); WKContextSetInitializationUserDataForInjectedBundle(context, initializationDictionary.get()); return context; }
void TestController::initialize(int argc, const char* argv[]) { platformInitialize(); if (argc < 2) { fputs("Usage: WebKitTestRunner [options] filename [filename2..n]\n", stderr); // FIXME: Refactor option parsing to allow us to print // an auto-generated list of options. exit(1); } bool printSupportedFeatures = false; for (int i = 1; i < argc; ++i) { std::string argument(argv[i]); if (argument == "--timeout" && i + 1 < argc) { m_longTimeout = atoi(argv[++i]); // Scale up the short timeout to match. m_shortTimeout = defaultShortTimeout * m_longTimeout / defaultLongTimeout; continue; } if (argument == "--no-timeout") { m_useWaitToDumpWatchdogTimer = false; continue; } if (argument == "--no-timeout-at-all") { m_useWaitToDumpWatchdogTimer = false; m_forceNoTimeout = true; continue; } if (argument == "--verbose") { m_verbose = true; continue; } if (argument == "--gc-between-tests") { m_gcBetweenTests = true; continue; } if (argument == "--pixel-tests" || argument == "-p") { m_shouldDumpPixelsForAllTests = true; continue; } if (argument == "--print-supported-features") { printSupportedFeatures = true; break; } // Skip any other arguments that begin with '--'. if (argument.length() >= 2 && argument[0] == '-' && argument[1] == '-') continue; m_paths.push_back(argument); } if (printSupportedFeatures) { // FIXME: On Windows, DumpRenderTree uses this to expose whether it supports 3d // transforms and accelerated compositing. When we support those features, we // should match DRT's behavior. exit(0); } m_usingServerMode = (m_paths.size() == 1 && m_paths[0] == "-"); if (m_usingServerMode) m_printSeparators = true; else m_printSeparators = m_paths.size() > 1; initializeInjectedBundlePath(); initializeTestPluginDirectory(); WKRetainPtr<WKStringRef> pageGroupIdentifier(AdoptWK, WKStringCreateWithUTF8CString("WebKitTestRunnerPageGroup")); m_pageGroup.adopt(WKPageGroupCreateWithIdentifier(pageGroupIdentifier.get())); m_context.adopt(WKContextCreateWithInjectedBundlePath(injectedBundlePath())); m_geolocationProvider = adoptPtr(new GeolocationProviderMock(m_context.get())); #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED > 1080 WKContextSetUsesNetworkProcess(m_context.get(), true); WKContextSetProcessModel(m_context.get(), kWKProcessModelMultipleSecondaryProcesses); #endif if (const char* dumpRenderTreeTemp = libraryPathForTesting()) { String temporaryFolder = String::fromUTF8(dumpRenderTreeTemp); // WebCore::pathByAppendingComponent is not used here because of the namespace, // which leads us to this ugly #ifdef and file path concatenation. #if OS(WINDOWS) const char separator = '\\'; #else const char separator = '/'; #endif WKContextSetApplicationCacheDirectory(m_context.get(), toWK(temporaryFolder + separator + "ApplicationCache").get()); WKContextSetDatabaseDirectory(m_context.get(), toWK(temporaryFolder + separator + "Databases").get()); WKContextSetLocalStorageDirectory(m_context.get(), toWK(temporaryFolder + separator + "LocalStorage").get()); WKContextSetDiskCacheDirectory(m_context.get(), toWK(temporaryFolder + separator + "Cache").get()); WKContextSetCookieStorageDirectory(m_context.get(), toWK(temporaryFolder + separator + "Cookies").get()); WKContextSetIconDatabasePath(m_context.get(), toWK(temporaryFolder + separator + "IconDatabase" + separator + "WebpageIcons.db").get()); } platformInitializeContext(); WKContextInjectedBundleClient injectedBundleClient = { kWKContextInjectedBundleClientCurrentVersion, this, didReceiveMessageFromInjectedBundle, didReceiveSynchronousMessageFromInjectedBundle, 0 // getInjectedBundleInitializationUserData }; WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient); WKNotificationManagerRef notificationManager = WKContextGetNotificationManager(m_context.get()); WKNotificationProvider notificationKit = m_webNotificationProvider.provider(); WKNotificationManagerSetProvider(notificationManager, ¬ificationKit); if (testPluginDirectory()) WKContextSetAdditionalPluginsDirectory(m_context.get(), testPluginDirectory()); createWebViewWithOptions(0); }
void TestController::initialize(int argc, const char* argv[]) { platformInitialize(); if (argc < 2) { fputs("Usage: WebKitTestRunner [options] filename [filename2..n]\n", stderr); // FIXME: Refactor option parsing to allow us to print // an auto-generated list of options. exit(1); } bool printSupportedFeatures = false; for (int i = 1; i < argc; ++i) { std::string argument(argv[i]); if (argument == "--timeout" && i + 1 < argc) { m_longTimeout = atoi(argv[++i]); // Scale up the short timeout to match. m_shortTimeout = defaultShortTimeout * m_longTimeout / defaultLongTimeout; continue; } if (argument == "--skip-pixel-test-if-no-baseline") { m_skipPixelTestOption = true; continue; } if (argument == "--pixel-tests") { m_dumpPixels = true; continue; } if (argument == "--verbose") { m_verbose = true; continue; } if (argument == "--gc-between-tests") { m_gcBetweenTests = true; continue; } if (argument == "--print-supported-features") { printSupportedFeatures = true; break; } // Skip any other arguments that begin with '--'. if (argument.length() >= 2 && argument[0] == '-' && argument[1] == '-') continue; m_paths.push_back(argument); } if (printSupportedFeatures) { // FIXME: On Windows, DumpRenderTree uses this to expose whether it supports 3d // transforms and accelerated compositing. When we support those features, we // should match DRT's behavior. exit(0); } m_usingServerMode = (m_paths.size() == 1 && m_paths[0] == "-"); if (m_usingServerMode) m_printSeparators = true; else m_printSeparators = m_paths.size() > 1; initializeInjectedBundlePath(); initializeTestPluginDirectory(); WKRetainPtr<WKStringRef> pageGroupIdentifier(AdoptWK, WKStringCreateWithUTF8CString("WebKitTestRunnerPageGroup")); m_pageGroup.adopt(WKPageGroupCreateWithIdentifier(pageGroupIdentifier.get())); m_context.adopt(WKContextCreateWithInjectedBundlePath(injectedBundlePath())); const char* path = libraryPathForTesting(); if (path) { Vector<char> databaseDirectory(strlen(path) + strlen("/Databases") + 1); sprintf(databaseDirectory.data(), "%s%s", path, "/Databases"); WKRetainPtr<WKStringRef> databaseDirectoryWK(AdoptWK, WKStringCreateWithUTF8CString(databaseDirectory.data())); WKContextSetDatabaseDirectory(m_context.get(), databaseDirectoryWK.get()); } platformInitializeContext(); WKContextInjectedBundleClient injectedBundleClient = { kWKContextInjectedBundleClientCurrentVersion, this, didReceiveMessageFromInjectedBundle, didReceiveSynchronousMessageFromInjectedBundle }; WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient); WKContextSetAdditionalPluginsDirectory(m_context.get(), testPluginDirectory()); m_mainWebView = adoptPtr(new PlatformWebView(m_context.get(), m_pageGroup.get())); WKPageUIClient pageUIClient = { kWKPageUIClientCurrentVersion, this, 0, // createNewPage_deprecatedForUseWithV0 0, // showPage 0, // close 0, // takeFocus 0, // focus 0, // unfocus 0, // runJavaScriptAlert 0, // runJavaScriptConfirm 0, // runJavaScriptPrompt 0, // setStatusText 0, // mouseDidMoveOverElement_deprecatedForUseWithV0 0, // missingPluginButtonClicked 0, // didNotHandleKeyEvent 0, // didNotHandleWheelEvent 0, // toolbarsAreVisible 0, // setToolbarsAreVisible 0, // menuBarIsVisible 0, // setMenuBarIsVisible 0, // statusBarIsVisible 0, // setStatusBarIsVisible 0, // isResizable 0, // setIsResizable getWindowFrameMainPage, setWindowFrameMainPage, runBeforeUnloadConfirmPanel, 0, // didDraw 0, // pageDidScroll exceededDatabaseQuota, 0, // runOpenPanel 0, // decidePolicyForGeolocationPermissionRequest 0, // headerHeight 0, // footerHeight 0, // drawHeader 0, // drawFooter 0, // printFrame runModal, 0, // didCompleteRubberBandForMainFrame 0, // saveDataToFileInDownloadsFolder 0, // shouldInterruptJavaScript createOtherPage, 0, // mouseDidMoveOverElement 0, // decidePolicyForNotificationPermissionRequest }; WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient); WKPageLoaderClient pageLoaderClient = { kWKPageLoaderClientCurrentVersion, this, 0, // didStartProvisionalLoadForFrame 0, // didReceiveServerRedirectForProvisionalLoadForFrame 0, // didFailProvisionalLoadWithErrorForFrame didCommitLoadForFrame, 0, // didFinishDocumentLoadForFrame didFinishLoadForFrame, 0, // didFailLoadWithErrorForFrame 0, // didSameDocumentNavigationForFrame 0, // didReceiveTitleForFrame 0, // didFirstLayoutForFrame 0, // didFirstVisuallyNonEmptyLayoutForFrame 0, // didRemoveFrameFromHierarchy 0, // didFailToInitializePlugin 0, // didDisplayInsecureContentForFrame 0, // canAuthenticateAgainstProtectionSpaceInFrame 0, // didReceiveAuthenticationChallengeInFrame 0, // didStartProgress 0, // didChangeProgress 0, // didFinishProgress 0, // didBecomeUnresponsive 0, // didBecomeResponsive processDidCrash, 0, // didChangeBackForwardList 0, // shouldGoToBackForwardListItem 0, // didRunInsecureContentForFrame 0, // didDetectXSSForFrame 0 // didNewFirstVisuallyNonEmptyLayout }; WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient); }
WebProcessProxy& WebContext::createNewWebProcess() { #if ENABLE(NETWORK_PROCESS) if (m_usesNetworkProcess) ensureNetworkProcess(); #endif RefPtr<WebProcessProxy> process = WebProcessProxy::create(*this); WebProcessCreationParameters parameters; parameters.injectedBundlePath = injectedBundlePath(); if (!parameters.injectedBundlePath.isEmpty()) SandboxExtension::createHandle(parameters.injectedBundlePath, SandboxExtension::ReadOnly, parameters.injectedBundlePathExtensionHandle); parameters.applicationCacheDirectory = applicationCacheDirectory(); if (!parameters.applicationCacheDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.applicationCacheDirectory, parameters.applicationCacheDirectoryExtensionHandle); parameters.databaseDirectory = databaseDirectory(); if (!parameters.databaseDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.databaseDirectory, parameters.databaseDirectoryExtensionHandle); parameters.diskCacheDirectory = diskCacheDirectory(); if (!parameters.diskCacheDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.diskCacheDirectory, parameters.diskCacheDirectoryExtensionHandle); parameters.cookieStorageDirectory = cookieStorageDirectory(); if (!parameters.cookieStorageDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle); parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession; parameters.cacheModel = m_cacheModel; parameters.languages = userPreferredLanguages(); copyToVector(m_schemesToRegisterAsEmptyDocument, parameters.urlSchemesRegistererdAsEmptyDocument); copyToVector(m_schemesToRegisterAsSecure, parameters.urlSchemesRegisteredAsSecure); copyToVector(m_schemesToSetDomainRelaxationForbiddenFor, parameters.urlSchemesForWhichDomainRelaxationIsForbidden); copyToVector(m_schemesToRegisterAsLocal, parameters.urlSchemesRegisteredAsLocal); copyToVector(m_schemesToRegisterAsNoAccess, parameters.urlSchemesRegisteredAsNoAccess); copyToVector(m_schemesToRegisterAsDisplayIsolated, parameters.urlSchemesRegisteredAsDisplayIsolated); copyToVector(m_schemesToRegisterAsCORSEnabled, parameters.urlSchemesRegisteredAsCORSEnabled); #if ENABLE(CACHE_PARTITIONING) copyToVector(m_schemesToRegisterAsCachePartitioned, parameters.urlSchemesRegisteredAsCachePartitioned); #endif parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath; parameters.shouldUseFontSmoothing = m_shouldUseFontSmoothing; parameters.iconDatabaseEnabled = !iconDatabasePath().isEmpty(); parameters.terminationTimeout = (m_processModel == ProcessModelSharedSecondaryProcess) ? sharedSecondaryProcessShutdownTimeout : 0; parameters.textCheckerState = TextChecker::state(); parameters.fullKeyboardAccessEnabled = WebProcessProxy::fullKeyboardAccessEnabled(); parameters.defaultRequestTimeoutInterval = API::URLRequest::defaultTimeoutInterval(); #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) // FIXME: There should be a generic way for supplements to add to the intialization parameters. supplement<WebNotificationManagerProxy>()->populateCopyOfNotificationPermissions(parameters.notificationPermissions); #endif #if ENABLE(NETWORK_PROCESS) parameters.usesNetworkProcess = m_usesNetworkProcess; #endif parameters.plugInAutoStartOriginHashes = m_plugInAutoStartProvider.autoStartOriginHashesCopy(); copyToVector(m_plugInAutoStartProvider.autoStartOrigins(), parameters.plugInAutoStartOrigins); parameters.memoryCacheDisabled = m_memoryCacheDisabled; #if ENABLE(SERVICE_CONTROLS) parameters.hasImageServices = ServicesController::shared().hasImageServices(); parameters.hasSelectionServices = ServicesController::shared().hasSelectionServices(); ServicesController::shared().refreshExistingServices(this); #endif // Add any platform specific parameters platformInitializeWebProcess(parameters); RefPtr<API::Object> injectedBundleInitializationUserData = m_injectedBundleClient.getInjectedBundleInitializationUserData(this); if (!injectedBundleInitializationUserData) injectedBundleInitializationUserData = m_injectedBundleInitializationUserData; process->send(Messages::WebProcess::InitializeWebProcess(parameters, WebContextUserMessageEncoder(injectedBundleInitializationUserData.get(), *process)), 0); #if PLATFORM(COCOA) process->send(Messages::WebProcess::SetQOS(webProcessLatencyQOS(), webProcessThroughputQOS()), 0); #endif if (WebPreferences::anyPagesAreUsingPrivateBrowsing()) process->send(Messages::WebProcess::EnsurePrivateBrowsingSession(SessionID::legacyPrivateSessionID()), 0); m_processes.append(process); if (m_processModel == ProcessModelSharedSecondaryProcess) { for (size_t i = 0; i != m_messagesToInjectedBundlePostedToEmptyContext.size(); ++i) { std::pair<String, RefPtr<API::Object>>& message = m_messagesToInjectedBundlePostedToEmptyContext[i]; IPC::ArgumentEncoder messageData; messageData.encode(message.first); messageData.encode(WebContextUserMessageEncoder(message.second.get(), *process)); process->send(Messages::WebProcess::PostInjectedBundleMessage(IPC::DataReference(messageData.buffer(), messageData.bufferSize())), 0); } m_messagesToInjectedBundlePostedToEmptyContext.clear(); } else ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty()); #if ENABLE(REMOTE_INSPECTOR) // Initialize remote inspector connection now that we have a sub-process that is hosting one of our web views. Inspector::RemoteInspector::shared(); #endif return *process; }
WebProcessProxy& WebProcessPool::createNewWebProcess() { ensureNetworkProcess(); Ref<WebProcessProxy> process = WebProcessProxy::create(*this); WebProcessCreationParameters parameters; parameters.injectedBundlePath = injectedBundlePath(); if (!parameters.injectedBundlePath.isEmpty()) SandboxExtension::createHandle(parameters.injectedBundlePath, SandboxExtension::ReadOnly, parameters.injectedBundlePathExtensionHandle); parameters.applicationCacheDirectory = m_configuration->applicationCacheDirectory(); parameters.applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName(); if (!parameters.applicationCacheDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.applicationCacheDirectory, parameters.applicationCacheDirectoryExtensionHandle); parameters.webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory(); if (!parameters.webSQLDatabaseDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.webSQLDatabaseDirectory, parameters.webSQLDatabaseDirectoryExtensionHandle); parameters.mediaCacheDirectory = m_configuration->mediaCacheDirectory(); if (!parameters.mediaCacheDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.mediaCacheDirectory, parameters.mediaCacheDirectoryExtensionHandle); #if PLATFORM(IOS) String cookieStorageDirectory = this->cookieStorageDirectory(); if (!cookieStorageDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle); String containerCachesDirectory = this->webContentCachesDirectory(); if (!containerCachesDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(containerCachesDirectory, parameters.containerCachesDirectoryExtensionHandle); String containerTemporaryDirectory = this->containerTemporaryDirectory(); if (!containerTemporaryDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(containerTemporaryDirectory, parameters.containerTemporaryDirectoryExtensionHandle); #endif parameters.mediaKeyStorageDirectory = m_configuration->mediaKeysStorageDirectory(); if (!parameters.mediaKeyStorageDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.mediaKeyStorageDirectory, parameters.mediaKeyStorageDirectoryExtensionHandle); parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession; parameters.cacheModel = cacheModel(); parameters.languages = userPreferredLanguages(); copyToVector(m_schemesToRegisterAsEmptyDocument, parameters.urlSchemesRegisteredAsEmptyDocument); copyToVector(m_schemesToRegisterAsSecure, parameters.urlSchemesRegisteredAsSecure); copyToVector(m_schemesToRegisterAsBypassingContentSecurityPolicy, parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy); copyToVector(m_schemesToSetDomainRelaxationForbiddenFor, parameters.urlSchemesForWhichDomainRelaxationIsForbidden); copyToVector(m_schemesToRegisterAsLocal, parameters.urlSchemesRegisteredAsLocal); copyToVector(m_schemesToRegisterAsNoAccess, parameters.urlSchemesRegisteredAsNoAccess); copyToVector(m_schemesToRegisterAsDisplayIsolated, parameters.urlSchemesRegisteredAsDisplayIsolated); copyToVector(m_schemesToRegisterAsCORSEnabled, parameters.urlSchemesRegisteredAsCORSEnabled); copyToVector(m_schemesToRegisterAsAlwaysRevalidated, parameters.urlSchemesRegisteredAsAlwaysRevalidated); #if ENABLE(CACHE_PARTITIONING) copyToVector(m_schemesToRegisterAsCachePartitioned, parameters.urlSchemesRegisteredAsCachePartitioned); #endif parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath; parameters.shouldUseFontSmoothing = m_shouldUseFontSmoothing; // FIXME: This leaves UI process and WebProcess disagreeing about the state if the client hasn't set the path. // iconDatabasePath is non-empty by default, but m_iconDatabase isn't enabled in UI process unless setDatabasePath is called explicitly. parameters.iconDatabaseEnabled = !iconDatabasePath().isEmpty(); parameters.terminationTimeout = 0; parameters.textCheckerState = TextChecker::state(); parameters.fullKeyboardAccessEnabled = WebProcessProxy::fullKeyboardAccessEnabled(); parameters.defaultRequestTimeoutInterval = API::URLRequest::defaultTimeoutInterval(); #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) // FIXME: There should be a generic way for supplements to add to the intialization parameters. supplement<WebNotificationManagerProxy>()->populateCopyOfNotificationPermissions(parameters.notificationPermissions); #endif parameters.plugInAutoStartOriginHashes = m_plugInAutoStartProvider.autoStartOriginHashesCopy(); copyToVector(m_plugInAutoStartProvider.autoStartOrigins(), parameters.plugInAutoStartOrigins); parameters.memoryCacheDisabled = m_memoryCacheDisabled; #if ENABLE(SERVICE_CONTROLS) auto& serviceController = ServicesController::singleton(); parameters.hasImageServices = serviceController.hasImageServices(); parameters.hasSelectionServices = serviceController.hasSelectionServices(); parameters.hasRichContentServices = serviceController.hasRichContentServices(); serviceController.refreshExistingServices(); #endif #if ENABLE(NETSCAPE_PLUGIN_API) parameters.pluginLoadClientPolicies = m_pluginLoadClientPolicies; #endif #if OS(LINUX) parameters.shouldEnableMemoryPressureReliefLogging = true; #endif parameters.resourceLoadStatisticsEnabled = resourceLoadStatisticsEnabled(); // Add any platform specific parameters platformInitializeWebProcess(parameters); RefPtr<API::Object> injectedBundleInitializationUserData = m_injectedBundleClient.getInjectedBundleInitializationUserData(this); if (!injectedBundleInitializationUserData) injectedBundleInitializationUserData = m_injectedBundleInitializationUserData; parameters.initializationUserData = UserData(process->transformObjectsToHandles(injectedBundleInitializationUserData.get())); process->send(Messages::WebProcess::InitializeWebProcess(parameters), 0); #if PLATFORM(COCOA) process->send(Messages::WebProcess::SetQOS(webProcessLatencyQOS(), webProcessThroughputQOS()), 0); #endif if (WebPreferences::anyPagesAreUsingPrivateBrowsing()) process->send(Messages::WebProcess::EnsurePrivateBrowsingSession(SessionID::legacyPrivateSessionID()), 0); if (m_automationSession) process->send(Messages::WebProcess::EnsureAutomationSessionProxy(m_automationSession->sessionIdentifier()), 0); m_processes.append(process.ptr()); ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty()); #if ENABLE(REMOTE_INSPECTOR) // Initialize remote inspector connection now that we have a sub-process that is hosting one of our web views. Inspector::RemoteInspector::singleton(); #endif return process; }