| 1 | /* |
| 2 | * Copyright (C) 2010-2016 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 | |
| 26 | #include "config.h" |
| 27 | #include "InjectedBundle.h" |
| 28 | |
| 29 | #include "APIArray.h" |
| 30 | #include "APIData.h" |
| 31 | #include "InjectedBundleScriptWorld.h" |
| 32 | #include "NetworkConnectionToWebProcessMessages.h" |
| 33 | #include "NetworkProcessConnection.h" |
| 34 | #include "NetworkSessionCreationParameters.h" |
| 35 | #include "NotificationPermissionRequestManager.h" |
| 36 | #include "UserData.h" |
| 37 | #include "WebConnectionToUIProcess.h" |
| 38 | #include "WebCoreArgumentCoders.h" |
| 39 | #include "WebFrame.h" |
| 40 | #include "WebFrameNetworkingContext.h" |
| 41 | #include "WebPage.h" |
| 42 | #include "WebPageGroupProxy.h" |
| 43 | #include "WebPreferencesKeys.h" |
| 44 | #include "WebPreferencesStore.h" |
| 45 | #include "WebProcess.h" |
| 46 | #include "WebProcessCreationParameters.h" |
| 47 | #include "WebProcessMessages.h" |
| 48 | #include "WebProcessPoolMessages.h" |
| 49 | #include "WebUserContentController.h" |
| 50 | #include "WebsiteDataStoreParameters.h" |
| 51 | #include <JavaScriptCore/APICast.h> |
| 52 | #include <JavaScriptCore/Exception.h> |
| 53 | #include <JavaScriptCore/JSLock.h> |
| 54 | #include <WebCore/ApplicationCache.h> |
| 55 | #include <WebCore/ApplicationCacheStorage.h> |
| 56 | #include <WebCore/CommonVM.h> |
| 57 | #include <WebCore/Document.h> |
| 58 | #include <WebCore/Frame.h> |
| 59 | #include <WebCore/FrameLoader.h> |
| 60 | #include <WebCore/FrameView.h> |
| 61 | #include <WebCore/GCController.h> |
| 62 | #include <WebCore/GeolocationClient.h> |
| 63 | #include <WebCore/GeolocationController.h> |
| 64 | #include <WebCore/GeolocationPosition.h> |
| 65 | #include <WebCore/JSDOMConvertBufferSource.h> |
| 66 | #include <WebCore/JSDOMExceptionHandling.h> |
| 67 | #include <WebCore/JSDOMWindow.h> |
| 68 | #include <WebCore/JSNotification.h> |
| 69 | #include <WebCore/Page.h> |
| 70 | #include <WebCore/PageGroup.h> |
| 71 | #include <WebCore/PrintContext.h> |
| 72 | #include <WebCore/RuntimeEnabledFeatures.h> |
| 73 | #include <WebCore/SWContextManager.h> |
| 74 | #include <WebCore/ScriptController.h> |
| 75 | #include <WebCore/SecurityOrigin.h> |
| 76 | #include <WebCore/SecurityPolicy.h> |
| 77 | #include <WebCore/Settings.h> |
| 78 | #include <WebCore/UserGestureIndicator.h> |
| 79 | #include <WebCore/UserScript.h> |
| 80 | #include <WebCore/UserStyleSheet.h> |
| 81 | #include <pal/SessionID.h> |
| 82 | #include <wtf/ProcessPrivilege.h> |
| 83 | |
| 84 | #if ENABLE(NOTIFICATIONS) |
| 85 | #include "WebNotificationManager.h" |
| 86 | #endif |
| 87 | |
| 88 | namespace WebKit { |
| 89 | using namespace WebCore; |
| 90 | using namespace JSC; |
| 91 | |
| 92 | RefPtr<InjectedBundle> InjectedBundle::create(WebProcessCreationParameters& parameters, API::Object* initializationUserData) |
| 93 | { |
| 94 | auto bundle = adoptRef(*new InjectedBundle(parameters)); |
| 95 | |
| 96 | bundle->m_sandboxExtension = SandboxExtension::create(WTFMove(parameters.injectedBundlePathExtensionHandle)); |
| 97 | if (!bundle->initialize(parameters, initializationUserData)) |
| 98 | return nullptr; |
| 99 | |
| 100 | return bundle; |
| 101 | } |
| 102 | |
| 103 | InjectedBundle::InjectedBundle(const WebProcessCreationParameters& parameters) |
| 104 | : m_path(parameters.injectedBundlePath) |
| 105 | , m_platformBundle(0) |
| 106 | , m_client(std::make_unique<API::InjectedBundle::Client>()) |
| 107 | { |
| 108 | } |
| 109 | |
| 110 | InjectedBundle::~InjectedBundle() |
| 111 | { |
| 112 | } |
| 113 | |
| 114 | void InjectedBundle::setClient(std::unique_ptr<API::InjectedBundle::Client>&& client) |
| 115 | { |
| 116 | if (!client) |
| 117 | m_client = std::make_unique<API::InjectedBundle::Client>(); |
| 118 | else |
| 119 | m_client = WTFMove(client); |
| 120 | } |
| 121 | |
| 122 | void InjectedBundle::setServiceWorkerProxyCreationCallback(void (*callback)(uint64_t)) |
| 123 | { |
| 124 | #if ENABLE(SERVICE_WORKER) |
| 125 | SWContextManager::singleton().setServiceWorkerCreationCallback(callback); |
| 126 | #endif |
| 127 | } |
| 128 | |
| 129 | void InjectedBundle::postMessage(const String& messageName, API::Object* messageBody) |
| 130 | { |
| 131 | auto& webProcess = WebProcess::singleton(); |
| 132 | webProcess.parentProcessConnection()->send(Messages::WebProcessPool::HandleMessage(messageName, UserData(webProcess.transformObjectsToHandles(messageBody))), 0); |
| 133 | } |
| 134 | |
| 135 | void InjectedBundle::postSynchronousMessage(const String& messageName, API::Object* messageBody, RefPtr<API::Object>& returnData) |
| 136 | { |
| 137 | UserData returnUserData; |
| 138 | |
| 139 | auto& webProcess = WebProcess::singleton(); |
| 140 | if (!webProcess.parentProcessConnection()->sendSync(Messages::WebProcessPool::HandleSynchronousMessage(messageName, UserData(webProcess.transformObjectsToHandles(messageBody))), |
| 141 | Messages::WebProcessPool::HandleSynchronousMessage::Reply(returnUserData), 0)) |
| 142 | returnData = nullptr; |
| 143 | else |
| 144 | returnData = webProcess.transformHandlesToObjects(returnUserData.object()); |
| 145 | } |
| 146 | |
| 147 | WebConnection* InjectedBundle::webConnectionToUIProcess() const |
| 148 | { |
| 149 | return WebProcess::singleton().webConnectionToUIProcess(); |
| 150 | } |
| 151 | |
| 152 | void InjectedBundle::overrideBoolPreferenceForTestRunner(WebPageGroupProxy* pageGroup, const String& preference, bool enabled) |
| 153 | { |
| 154 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 155 | |
| 156 | if (preference == "WebKitTabToLinksPreferenceKey" ) { |
| 157 | WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::tabsToLinksKey(), enabled); |
| 158 | for (auto* page : pages) |
| 159 | WebPage::fromCorePage(page)->setTabToLinksEnabled(enabled); |
| 160 | } |
| 161 | |
| 162 | if (preference == "WebKit2AsynchronousPluginInitializationEnabled" ) { |
| 163 | WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledKey(), enabled); |
| 164 | for (auto* page : pages) |
| 165 | WebPage::fromCorePage(page)->setAsynchronousPluginInitializationEnabled(enabled); |
| 166 | } |
| 167 | |
| 168 | if (preference == "WebKit2AsynchronousPluginInitializationEnabledForAllPlugins" ) { |
| 169 | WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledForAllPluginsKey(), enabled); |
| 170 | for (auto* page : pages) |
| 171 | WebPage::fromCorePage(page)->setAsynchronousPluginInitializationEnabledForAllPlugins(enabled); |
| 172 | } |
| 173 | |
| 174 | if (preference == "WebKit2ArtificialPluginInitializationDelayEnabled" ) { |
| 175 | WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::artificialPluginInitializationDelayEnabledKey(), enabled); |
| 176 | for (auto* page : pages) |
| 177 | WebPage::fromCorePage(page)->setArtificialPluginInitializationDelayEnabled(enabled); |
| 178 | } |
| 179 | |
| 180 | #if ENABLE(SERVICE_CONTROLS) |
| 181 | if (preference == "WebKitImageControlsEnabled" ) { |
| 182 | WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::imageControlsEnabledKey(), enabled); |
| 183 | for (auto* page : pages) |
| 184 | page->settings().setImageControlsEnabled(enabled); |
| 185 | return; |
| 186 | } |
| 187 | #endif |
| 188 | |
| 189 | if (preference == "WebKitWebAnimationsEnabled" ) |
| 190 | RuntimeEnabledFeatures::sharedFeatures().setWebAnimationsEnabled(enabled); |
| 191 | |
| 192 | if (preference == "WebKitWebAnimationsCSSIntegrationEnabled" ) |
| 193 | RuntimeEnabledFeatures::sharedFeatures().setWebAnimationsCSSIntegrationEnabled(enabled); |
| 194 | |
| 195 | if (preference == "WebKitCacheAPIEnabled" ) |
| 196 | RuntimeEnabledFeatures::sharedFeatures().setCacheAPIEnabled(enabled); |
| 197 | |
| 198 | #if ENABLE(STREAMS_API) |
| 199 | if (preference == "WebKitReadableByteStreamAPIEnabled" ) |
| 200 | RuntimeEnabledFeatures::sharedFeatures().setReadableByteStreamAPIEnabled(enabled); |
| 201 | if (preference == "WebKitWritableStreamAPIEnabled" ) |
| 202 | RuntimeEnabledFeatures::sharedFeatures().setWritableStreamAPIEnabled(enabled); |
| 203 | #endif |
| 204 | |
| 205 | if (preference == "WebKitInteractiveFormValidationEnabled" ) |
| 206 | RuntimeEnabledFeatures::sharedFeatures().setInteractiveFormValidationEnabled(enabled); |
| 207 | |
| 208 | #if ENABLE(WEBGL2) |
| 209 | if (preference == "WebKitWebGL2Enabled" ) |
| 210 | RuntimeEnabledFeatures::sharedFeatures().setWebGL2Enabled(enabled); |
| 211 | #endif |
| 212 | |
| 213 | #if ENABLE(WEBGPU) |
| 214 | if (preference == "WebKitWebGPUEnabled" ) |
| 215 | RuntimeEnabledFeatures::sharedFeatures().setWebGPUEnabled(enabled); |
| 216 | #endif |
| 217 | |
| 218 | if (preference == "WebKitModernMediaControlsEnabled" ) |
| 219 | RuntimeEnabledFeatures::sharedFeatures().setModernMediaControlsEnabled(enabled); |
| 220 | |
| 221 | #if ENABLE(ENCRYPTED_MEDIA) |
| 222 | if (preference == "WebKitEncryptedMediaAPIEnabled" ) { |
| 223 | WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::encryptedMediaAPIEnabledKey(), enabled); |
| 224 | RuntimeEnabledFeatures::sharedFeatures().setEncryptedMediaAPIEnabled(enabled); |
| 225 | } |
| 226 | #endif |
| 227 | |
| 228 | #if ENABLE(MEDIA_STREAM) |
| 229 | if (preference == "WebKitMediaDevicesEnabled" ) |
| 230 | RuntimeEnabledFeatures::sharedFeatures().setMediaDevicesEnabled(enabled); |
| 231 | if (preference == "WebKitScreenCaptureEnabled" ) |
| 232 | RuntimeEnabledFeatures::sharedFeatures().setScreenCaptureEnabled(enabled); |
| 233 | #endif |
| 234 | |
| 235 | #if ENABLE(WEB_RTC) |
| 236 | if (preference == "WebKitWebRTCMDNSICECandidatesEnabled" ) |
| 237 | RuntimeEnabledFeatures::sharedFeatures().setWebRTCMDNSICECandidatesEnabled(enabled); |
| 238 | if (preference == "WebKitWebRTCUnifiedPlanEnabled" ) |
| 239 | RuntimeEnabledFeatures::sharedFeatures().setWebRTCUnifiedPlanEnabled(enabled); |
| 240 | #endif |
| 241 | |
| 242 | if (preference == "WebKitIsSecureContextAttributeEnabled" ) { |
| 243 | WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::isSecureContextAttributeEnabledKey(), enabled); |
| 244 | RuntimeEnabledFeatures::sharedFeatures().setIsSecureContextAttributeEnabled(enabled); |
| 245 | } |
| 246 | |
| 247 | if (preference == "WebKitWebAPIStatisticsEnabled" ) |
| 248 | RuntimeEnabledFeatures::sharedFeatures().setWebAPIStatisticsEnabled(enabled); |
| 249 | |
| 250 | if (preference == "CSSCustomPropertiesAndValuesEnabled" ) |
| 251 | RuntimeEnabledFeatures::sharedFeatures().setCSSCustomPropertiesAndValuesEnabled(enabled); |
| 252 | |
| 253 | #if ENABLE(LAYOUT_FORMATTING_CONTEXT) |
| 254 | if (preference == "LayoutFormattingContextEnabled" ) |
| 255 | RuntimeEnabledFeatures::sharedFeatures().setLayoutFormattingContextEnabled(enabled); |
| 256 | #endif |
| 257 | |
| 258 | #if ENABLE(CSS_PAINTING_API) |
| 259 | if (preference == "CSSPaintingAPIEnabled" ) |
| 260 | RuntimeEnabledFeatures::sharedFeatures().setCSSPaintingAPIEnabled(enabled); |
| 261 | #endif |
| 262 | |
| 263 | #if ENABLE(CSS_TYPED_OM) |
| 264 | if (preference == "CSSTypedOMEnabled" ) |
| 265 | RuntimeEnabledFeatures::sharedFeatures().setCSSTypedOMEnabled(enabled); |
| 266 | #endif |
| 267 | |
| 268 | // Map the names used in LayoutTests with the names used in WebCore::Settings and WebPreferencesStore. |
| 269 | #define FOR_EACH_OVERRIDE_BOOL_PREFERENCE(macro) \ |
| 270 | macro(WebKitJavaEnabled, JavaEnabled, javaEnabled) \ |
| 271 | macro(WebKitJavaScriptEnabled, ScriptEnabled, javaScriptEnabled) \ |
| 272 | macro(WebKitPluginsEnabled, PluginsEnabled, pluginsEnabled) \ |
| 273 | macro(WebKitUsesPageCachePreferenceKey, UsesPageCache, usesPageCache) \ |
| 274 | macro(WebKitWebAudioEnabled, WebAudioEnabled, webAudioEnabled) \ |
| 275 | macro(WebKitWebGLEnabled, WebGLEnabled, webGLEnabled) \ |
| 276 | macro(WebKitXSSAuditorEnabled, XSSAuditorEnabled, xssAuditorEnabled) \ |
| 277 | macro(WebKitShouldRespectImageOrientation, ShouldRespectImageOrientation, shouldRespectImageOrientation) \ |
| 278 | macro(WebKitDisplayImagesKey, LoadsImagesAutomatically, loadsImagesAutomatically) \ |
| 279 | macro(WebKitLargeImageAsyncDecodingEnabled, LargeImageAsyncDecodingEnabled, largeImageAsyncDecodingEnabled) \ |
| 280 | macro(WebKitAnimatedImageAsyncDecodingEnabled, AnimatedImageAsyncDecodingEnabled, animatedImageAsyncDecodingEnabled) \ |
| 281 | \ |
| 282 | |
| 283 | #define OVERRIDE_PREFERENCE_AND_SET_IN_EXISTING_PAGES(TestRunnerName, SettingsName, WebPreferencesName) \ |
| 284 | if (preference == #TestRunnerName) { \ |
| 285 | WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::WebPreferencesName##Key(), enabled); \ |
| 286 | for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) \ |
| 287 | (*iter)->settings().set##SettingsName(enabled); \ |
| 288 | return; \ |
| 289 | } |
| 290 | |
| 291 | FOR_EACH_OVERRIDE_BOOL_PREFERENCE(OVERRIDE_PREFERENCE_AND_SET_IN_EXISTING_PAGES) |
| 292 | |
| 293 | OVERRIDE_PREFERENCE_AND_SET_IN_EXISTING_PAGES(WebKitHiddenPageDOMTimerThrottlingEnabled, HiddenPageDOMTimerThrottlingEnabled, hiddenPageDOMTimerThrottlingEnabled) |
| 294 | |
| 295 | #undef OVERRIDE_PREFERENCE_AND_SET_IN_EXISTING_PAGES |
| 296 | #undef FOR_EACH_OVERRIDE_BOOL_PREFERENCE |
| 297 | } |
| 298 | |
| 299 | void InjectedBundle::setAllowUniversalAccessFromFileURLs(WebPageGroupProxy* pageGroup, bool enabled) |
| 300 | { |
| 301 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 302 | for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) |
| 303 | (*iter)->settings().setAllowUniversalAccessFromFileURLs(enabled); |
| 304 | } |
| 305 | |
| 306 | void InjectedBundle::setAllowFileAccessFromFileURLs(WebPageGroupProxy* pageGroup, bool enabled) |
| 307 | { |
| 308 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 309 | for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) |
| 310 | (*iter)->settings().setAllowFileAccessFromFileURLs(enabled); |
| 311 | } |
| 312 | |
| 313 | void InjectedBundle::setNeedsStorageAccessFromFileURLsQuirk(WebPageGroupProxy* pageGroup, bool needsQuirk) |
| 314 | { |
| 315 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 316 | for (auto page : pages) |
| 317 | page->settings().setNeedsStorageAccessFromFileURLsQuirk(needsQuirk); |
| 318 | } |
| 319 | |
| 320 | void InjectedBundle::setMinimumLogicalFontSize(WebPageGroupProxy* pageGroup, int size) |
| 321 | { |
| 322 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 323 | for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) |
| 324 | (*iter)->settings().setMinimumLogicalFontSize(size); |
| 325 | } |
| 326 | |
| 327 | void InjectedBundle::setFrameFlatteningEnabled(WebPageGroupProxy* pageGroup, bool enabled) |
| 328 | { |
| 329 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 330 | for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) |
| 331 | (*iter)->settings().setFrameFlattening(enabled ? FrameFlattening::FullyEnabled : FrameFlattening::Disabled); |
| 332 | } |
| 333 | |
| 334 | void InjectedBundle::setAsyncFrameScrollingEnabled(WebPageGroupProxy* pageGroup, bool enabled) |
| 335 | { |
| 336 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 337 | for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) |
| 338 | (*iter)->settings().setAsyncFrameScrollingEnabled(enabled); |
| 339 | } |
| 340 | |
| 341 | void InjectedBundle::setJavaScriptCanAccessClipboard(WebPageGroupProxy* pageGroup, bool enabled) |
| 342 | { |
| 343 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 344 | for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) |
| 345 | (*iter)->settings().setJavaScriptCanAccessClipboard(enabled); |
| 346 | } |
| 347 | |
| 348 | void InjectedBundle::setPrivateBrowsingEnabled(WebPageGroupProxy* pageGroup, bool enabled) |
| 349 | { |
| 350 | ASSERT(!hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies)); |
| 351 | if (enabled) |
| 352 | WebProcess::singleton().ensureLegacyPrivateBrowsingSessionInNetworkProcess(); |
| 353 | |
| 354 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 355 | for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) |
| 356 | (*iter)->enableLegacyPrivateBrowsing(enabled); |
| 357 | } |
| 358 | |
| 359 | void InjectedBundle::setUseDashboardCompatibilityMode(WebPageGroupProxy* pageGroup, bool enabled) |
| 360 | { |
| 361 | #if ENABLE(DASHBOARD_SUPPORT) |
| 362 | for (auto& page : PageGroup::pageGroup(pageGroup->identifier())->pages()) |
| 363 | page->settings().setUsesDashboardBackwardCompatibilityMode(enabled); |
| 364 | #endif |
| 365 | } |
| 366 | |
| 367 | void InjectedBundle::(WebPageGroupProxy* pageGroup, bool enabled) |
| 368 | { |
| 369 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 370 | HashSet<Page*>::const_iterator end = pages.end(); |
| 371 | for (HashSet<Page*>::const_iterator iter = pages.begin(); iter != end; ++iter) |
| 372 | (*iter)->settings().setJavaScriptCanOpenWindowsAutomatically(!enabled); |
| 373 | } |
| 374 | |
| 375 | void InjectedBundle::setAuthorAndUserStylesEnabled(WebPageGroupProxy* pageGroup, bool enabled) |
| 376 | { |
| 377 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 378 | for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) |
| 379 | (*iter)->settings().setAuthorAndUserStylesEnabled(enabled); |
| 380 | } |
| 381 | |
| 382 | void InjectedBundle::setSpatialNavigationEnabled(WebPageGroupProxy* pageGroup, bool enabled) |
| 383 | { |
| 384 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 385 | for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) |
| 386 | (*iter)->settings().setSpatialNavigationEnabled(enabled); |
| 387 | } |
| 388 | |
| 389 | void InjectedBundle::addOriginAccessWhitelistEntry(const String& sourceOrigin, const String& destinationProtocol, const String& destinationHost, bool allowDestinationSubdomains) |
| 390 | { |
| 391 | SecurityPolicy::addOriginAccessWhitelistEntry(SecurityOrigin::createFromString(sourceOrigin).get(), destinationProtocol, destinationHost, allowDestinationSubdomains); |
| 392 | WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::AddOriginAccessWhitelistEntry { sourceOrigin, destinationProtocol, destinationHost, allowDestinationSubdomains }, 0); |
| 393 | |
| 394 | } |
| 395 | |
| 396 | void InjectedBundle::removeOriginAccessWhitelistEntry(const String& sourceOrigin, const String& destinationProtocol, const String& destinationHost, bool allowDestinationSubdomains) |
| 397 | { |
| 398 | SecurityPolicy::removeOriginAccessWhitelistEntry(SecurityOrigin::createFromString(sourceOrigin).get(), destinationProtocol, destinationHost, allowDestinationSubdomains); |
| 399 | WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RemoveOriginAccessWhitelistEntry { sourceOrigin, destinationProtocol, destinationHost, allowDestinationSubdomains }, 0); |
| 400 | } |
| 401 | |
| 402 | void InjectedBundle::resetOriginAccessWhitelists() |
| 403 | { |
| 404 | SecurityPolicy::resetOriginAccessWhitelists(); |
| 405 | WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::ResetOriginAccessWhitelists { }, 0); |
| 406 | } |
| 407 | |
| 408 | void InjectedBundle::setAsynchronousSpellCheckingEnabled(WebPageGroupProxy* pageGroup, bool enabled) |
| 409 | { |
| 410 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 411 | for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) |
| 412 | (*iter)->settings().setAsynchronousSpellCheckingEnabled(enabled); |
| 413 | } |
| 414 | |
| 415 | int InjectedBundle::numberOfPages(WebFrame* frame, double pageWidthInPixels, double pageHeightInPixels) |
| 416 | { |
| 417 | Frame* coreFrame = frame ? frame->coreFrame() : 0; |
| 418 | if (!coreFrame) |
| 419 | return -1; |
| 420 | if (!pageWidthInPixels) |
| 421 | pageWidthInPixels = coreFrame->view()->width(); |
| 422 | if (!pageHeightInPixels) |
| 423 | pageHeightInPixels = coreFrame->view()->height(); |
| 424 | |
| 425 | return PrintContext::numberOfPages(*coreFrame, FloatSize(pageWidthInPixels, pageHeightInPixels)); |
| 426 | } |
| 427 | |
| 428 | int InjectedBundle::pageNumberForElementById(WebFrame* frame, const String& id, double pageWidthInPixels, double pageHeightInPixels) |
| 429 | { |
| 430 | Frame* coreFrame = frame ? frame->coreFrame() : 0; |
| 431 | if (!coreFrame) |
| 432 | return -1; |
| 433 | |
| 434 | Element* element = coreFrame->document()->getElementById(id); |
| 435 | if (!element) |
| 436 | return -1; |
| 437 | |
| 438 | if (!pageWidthInPixels) |
| 439 | pageWidthInPixels = coreFrame->view()->width(); |
| 440 | if (!pageHeightInPixels) |
| 441 | pageHeightInPixels = coreFrame->view()->height(); |
| 442 | |
| 443 | return PrintContext::pageNumberForElement(element, FloatSize(pageWidthInPixels, pageHeightInPixels)); |
| 444 | } |
| 445 | |
| 446 | String InjectedBundle::pageSizeAndMarginsInPixels(WebFrame* frame, int pageIndex, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) |
| 447 | { |
| 448 | Frame* coreFrame = frame ? frame->coreFrame() : 0; |
| 449 | if (!coreFrame) |
| 450 | return String(); |
| 451 | |
| 452 | return PrintContext::pageSizeAndMarginsInPixels(coreFrame, pageIndex, width, height, marginTop, marginRight, marginBottom, marginLeft); |
| 453 | } |
| 454 | |
| 455 | bool InjectedBundle::isPageBoxVisible(WebFrame* frame, int pageIndex) |
| 456 | { |
| 457 | Frame* coreFrame = frame ? frame->coreFrame() : 0; |
| 458 | if (!coreFrame) |
| 459 | return false; |
| 460 | |
| 461 | return PrintContext::isPageBoxVisible(coreFrame, pageIndex); |
| 462 | } |
| 463 | |
| 464 | bool InjectedBundle::isProcessingUserGesture() |
| 465 | { |
| 466 | return UserGestureIndicator::processingUserGesture(); |
| 467 | } |
| 468 | |
| 469 | void InjectedBundle::addUserScript(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld, String&& source, String&& url, API::Array* whitelist, API::Array* blacklist, WebCore::UserScriptInjectionTime injectionTime, WebCore::UserContentInjectedFrames injectedFrames) |
| 470 | { |
| 471 | UserScript userScript { WTFMove(source), URL(URL(), url), whitelist ? whitelist->toStringVector() : Vector<String>(), blacklist ? blacklist->toStringVector() : Vector<String>(), injectionTime, injectedFrames }; |
| 472 | |
| 473 | pageGroup->userContentController().addUserScript(*scriptWorld, WTFMove(userScript)); |
| 474 | } |
| 475 | |
| 476 | void InjectedBundle::addUserStyleSheet(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld, const String& source, const String& url, API::Array* whitelist, API::Array* blacklist, WebCore::UserContentInjectedFrames injectedFrames) |
| 477 | { |
| 478 | UserStyleSheet userStyleSheet{ source, URL(URL(), url), whitelist ? whitelist->toStringVector() : Vector<String>(), blacklist ? blacklist->toStringVector() : Vector<String>(), injectedFrames, UserStyleUserLevel }; |
| 479 | |
| 480 | pageGroup->userContentController().addUserStyleSheet(*scriptWorld, WTFMove(userStyleSheet)); |
| 481 | } |
| 482 | |
| 483 | void InjectedBundle::removeUserScript(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld, const String& url) |
| 484 | { |
| 485 | pageGroup->userContentController().removeUserScriptWithURL(*scriptWorld, URL(URL(), url)); |
| 486 | } |
| 487 | |
| 488 | void InjectedBundle::removeUserStyleSheet(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld, const String& url) |
| 489 | { |
| 490 | pageGroup->userContentController().removeUserStyleSheetWithURL(*scriptWorld, URL(URL(), url)); |
| 491 | } |
| 492 | |
| 493 | void InjectedBundle::removeUserScripts(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld) |
| 494 | { |
| 495 | pageGroup->userContentController().removeUserScripts(*scriptWorld); |
| 496 | } |
| 497 | |
| 498 | void InjectedBundle::removeUserStyleSheets(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld) |
| 499 | { |
| 500 | pageGroup->userContentController().removeUserStyleSheets(*scriptWorld); |
| 501 | } |
| 502 | |
| 503 | void InjectedBundle::removeAllUserContent(WebPageGroupProxy* pageGroup) |
| 504 | { |
| 505 | pageGroup->userContentController().removeAllUserContent(); |
| 506 | } |
| 507 | |
| 508 | void InjectedBundle::garbageCollectJavaScriptObjects() |
| 509 | { |
| 510 | GCController::singleton().garbageCollectNow(); |
| 511 | } |
| 512 | |
| 513 | void InjectedBundle::garbageCollectJavaScriptObjectsOnAlternateThreadForDebugging(bool waitUntilDone) |
| 514 | { |
| 515 | GCController::singleton().garbageCollectOnAlternateThreadForDebugging(waitUntilDone); |
| 516 | } |
| 517 | |
| 518 | size_t InjectedBundle::javaScriptObjectsCount() |
| 519 | { |
| 520 | JSLockHolder lock(commonVM()); |
| 521 | return commonVM().heap.objectCount(); |
| 522 | } |
| 523 | |
| 524 | void InjectedBundle::reportException(JSContextRef context, JSValueRef exception) |
| 525 | { |
| 526 | if (!context || !exception) |
| 527 | return; |
| 528 | |
| 529 | JSC::ExecState* execState = toJS(context); |
| 530 | JSLockHolder lock(execState); |
| 531 | |
| 532 | // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a Page. |
| 533 | JSC::JSGlobalObject* globalObject = execState->lexicalGlobalObject(); |
| 534 | if (!toJSDOMWindow(globalObject->vm(), globalObject)) |
| 535 | return; |
| 536 | |
| 537 | WebCore::reportException(execState, toJS(execState, exception)); |
| 538 | } |
| 539 | |
| 540 | void InjectedBundle::didCreatePage(WebPage* page) |
| 541 | { |
| 542 | m_client->didCreatePage(*this, *page); |
| 543 | } |
| 544 | |
| 545 | void InjectedBundle::willDestroyPage(WebPage* page) |
| 546 | { |
| 547 | m_client->willDestroyPage(*this, *page); |
| 548 | } |
| 549 | |
| 550 | void InjectedBundle::didInitializePageGroup(WebPageGroupProxy* pageGroup) |
| 551 | { |
| 552 | m_client->didInitializePageGroup(*this, *pageGroup); |
| 553 | } |
| 554 | |
| 555 | void InjectedBundle::didReceiveMessage(const String& messageName, API::Object* messageBody) |
| 556 | { |
| 557 | m_client->didReceiveMessage(*this, messageName, messageBody); |
| 558 | } |
| 559 | |
| 560 | void InjectedBundle::didReceiveMessageToPage(WebPage* page, const String& messageName, API::Object* messageBody) |
| 561 | { |
| 562 | m_client->didReceiveMessageToPage(*this, *page, messageName, messageBody); |
| 563 | } |
| 564 | |
| 565 | void InjectedBundle::setUserStyleSheetLocation(WebPageGroupProxy* pageGroup, const String& location) |
| 566 | { |
| 567 | const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages(); |
| 568 | for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) |
| 569 | (*iter)->settings().setUserStyleSheetLocation(URL(URL(), location)); |
| 570 | } |
| 571 | |
| 572 | void InjectedBundle::setWebNotificationPermission(WebPage* page, const String& originString, bool allowed) |
| 573 | { |
| 574 | #if ENABLE(NOTIFICATIONS) |
| 575 | page->notificationPermissionRequestManager()->setPermissionLevelForTesting(originString, allowed); |
| 576 | #else |
| 577 | UNUSED_PARAM(page); |
| 578 | UNUSED_PARAM(originString); |
| 579 | UNUSED_PARAM(allowed); |
| 580 | #endif |
| 581 | } |
| 582 | |
| 583 | void InjectedBundle::removeAllWebNotificationPermissions(WebPage* page) |
| 584 | { |
| 585 | #if ENABLE(NOTIFICATIONS) |
| 586 | page->notificationPermissionRequestManager()->removeAllPermissionsForTesting(); |
| 587 | #else |
| 588 | UNUSED_PARAM(page); |
| 589 | #endif |
| 590 | } |
| 591 | |
| 592 | uint64_t InjectedBundle::webNotificationID(JSContextRef jsContext, JSValueRef jsNotification) |
| 593 | { |
| 594 | #if ENABLE(NOTIFICATIONS) |
| 595 | WebCore::Notification* notification = JSNotification::toWrapped(toJS(jsContext)->vm(), toJS(toJS(jsContext), jsNotification)); |
| 596 | if (!notification) |
| 597 | return 0; |
| 598 | return WebProcess::singleton().supplement<WebNotificationManager>()->notificationIDForTesting(notification); |
| 599 | #else |
| 600 | UNUSED_PARAM(jsContext); |
| 601 | UNUSED_PARAM(jsNotification); |
| 602 | return 0; |
| 603 | #endif |
| 604 | } |
| 605 | |
| 606 | // FIXME Get rid of this function and move it into WKBundle.cpp. |
| 607 | Ref<API::Data> InjectedBundle::createWebDataFromUint8Array(JSContextRef context, JSValueRef data) |
| 608 | { |
| 609 | JSC::ExecState* execState = toJS(context); |
| 610 | JSLockHolder lock(execState); |
| 611 | RefPtr<Uint8Array> arrayData = WebCore::toUnsharedUint8Array(execState->vm(), toJS(execState, data)); |
| 612 | return API::Data::create(static_cast<unsigned char*>(arrayData->baseAddress()), arrayData->byteLength()); |
| 613 | } |
| 614 | |
| 615 | InjectedBundle::DocumentIDToURLMap InjectedBundle::liveDocumentURLs(WebPageGroupProxy* pageGroup, bool excludeDocumentsInPageGroupPages) |
| 616 | { |
| 617 | DocumentIDToURLMap result; |
| 618 | |
| 619 | for (const auto* document : Document::allDocuments()) |
| 620 | result.add(document->identifier().toUInt64(), document->url().string()); |
| 621 | |
| 622 | if (excludeDocumentsInPageGroupPages) { |
| 623 | for (const auto* page : PageGroup::pageGroup(pageGroup->identifier())->pages()) { |
| 624 | for (const auto* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) { |
| 625 | if (!frame->document()) |
| 626 | continue; |
| 627 | result.remove(frame->document()->identifier().toUInt64()); |
| 628 | } |
| 629 | } |
| 630 | } |
| 631 | |
| 632 | return result; |
| 633 | } |
| 634 | |
| 635 | void InjectedBundle::setTabKeyCyclesThroughElements(WebPage* page, bool enabled) |
| 636 | { |
| 637 | page->corePage()->setTabKeyCyclesThroughElements(enabled); |
| 638 | } |
| 639 | |
| 640 | void InjectedBundle::setWebAnimationsEnabled(bool enabled) |
| 641 | { |
| 642 | RuntimeEnabledFeatures::sharedFeatures().setWebAnimationsEnabled(enabled); |
| 643 | } |
| 644 | |
| 645 | void InjectedBundle::setWebAnimationsCSSIntegrationEnabled(bool enabled) |
| 646 | { |
| 647 | RuntimeEnabledFeatures::sharedFeatures().setWebAnimationsCSSIntegrationEnabled(enabled); |
| 648 | } |
| 649 | |
| 650 | } // namespace WebKit |
| 651 | |