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