../WebCore: [Windows] Refactor RuntimeEnabledFeatures as a Singleton
[WebKit-https.git] / Source / WebKit2 / WebProcess / InjectedBundle / InjectedBundle.cpp
1 /*
2  * Copyright (C) 2010, 2013 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 "Arguments.h"
30 #include "ImmutableArray.h"
31 #include "InjectedBundleScriptWorld.h"
32 #include "InjectedBundleUserMessageCoders.h"
33 #include "LayerTreeHost.h"
34 #include "NotificationPermissionRequestManager.h"
35 #include "WKAPICast.h"
36 #include "WKBundleAPICast.h"
37 #include "WebApplicationCacheManager.h"
38 #include "WebConnectionToUIProcess.h"
39 #include "WebContextMessageKinds.h"
40 #include "WebCookieManager.h"
41 #include "WebCoreArgumentCoders.h"
42 #include "WebData.h"
43 #include "WebDatabaseManager.h"
44 #include "WebFrame.h"
45 #include "WebFrameNetworkingContext.h"
46 #include "WebPage.h"
47 #include "WebPreferencesStore.h"
48 #include "WebProcess.h"
49 #include <JavaScriptCore/APICast.h>
50 #include <JavaScriptCore/JSLock.h>
51 #include <WebCore/ApplicationCache.h>
52 #include <WebCore/ApplicationCacheStorage.h>
53 #include <WebCore/Frame.h>
54 #include <WebCore/FrameLoader.h>
55 #include <WebCore/FrameView.h>
56 #include <WebCore/GCController.h>
57 #include <WebCore/GeolocationClient.h>
58 #include <WebCore/GeolocationController.h>
59 #include <WebCore/GeolocationPosition.h>
60 #include <WebCore/JSDOMWindow.h>
61 #include <WebCore/JSNotification.h>
62 #include <WebCore/Page.h>
63 #include <WebCore/PageGroup.h>
64 #include <WebCore/PrintContext.h>
65 #include <WebCore/ResourceHandle.h>
66 #include <WebCore/ResourceLoadScheduler.h>
67 #include <WebCore/ScriptController.h>
68 #include <WebCore/SecurityOrigin.h>
69 #include <WebCore/SecurityPolicy.h>
70 #include <WebCore/Settings.h>
71 #include <WebCore/UserGestureIndicator.h>
72
73 #if ENABLE(SHADOW_DOM) || ENABLE(CSS_REGIONS) || ENABLE(IFRAME_SEAMLESS) || ENABLE(CSS_COMPOSITING)
74 #include <WebCore/RuntimeEnabledFeatures.h>
75 #endif
76
77 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
78 #include "WebNotificationManager.h"
79 #endif
80
81 using namespace WebCore;
82 using namespace JSC;
83
84 namespace WebKit {
85
86 InjectedBundle::InjectedBundle(const String& path)
87     : m_path(path)
88     , m_platformBundle(0)
89 {
90     initializeClient(0);
91 }
92
93 InjectedBundle::~InjectedBundle()
94 {
95 }
96
97 void InjectedBundle::initializeClient(WKBundleClient* client)
98 {
99     m_client.initialize(client);
100 }
101
102 void InjectedBundle::postMessage(const String& messageName, APIObject* messageBody)
103 {
104     auto encoder = std::make_unique<CoreIPC::MessageEncoder>(WebContextLegacyMessages::messageReceiverName(), WebContextLegacyMessages::postMessageMessageName(), 0);
105     encoder->encode(messageName);
106     encoder->encode(InjectedBundleUserMessageEncoder(messageBody));
107
108     WebProcess::shared().parentProcessConnection()->sendMessage(std::move(encoder));
109 }
110
111 void InjectedBundle::postSynchronousMessage(const String& messageName, APIObject* messageBody, RefPtr<APIObject>& returnData)
112 {
113     InjectedBundleUserMessageDecoder messageDecoder(returnData);
114
115     uint64_t syncRequestID;
116     std::unique_ptr<CoreIPC::MessageEncoder> encoder = WebProcess::shared().parentProcessConnection()->createSyncMessageEncoder(WebContextLegacyMessages::messageReceiverName(), WebContextLegacyMessages::postSynchronousMessageMessageName(), 0, syncRequestID);
117     encoder->encode(messageName);
118     encoder->encode(InjectedBundleUserMessageEncoder(messageBody));
119
120     std::unique_ptr<CoreIPC::MessageDecoder> replyDecoder = WebProcess::shared().parentProcessConnection()->sendSyncMessage(syncRequestID, std::move(encoder), CoreIPC::Connection::NoTimeout);
121     if (!replyDecoder || !replyDecoder->decode(messageDecoder)) {
122         returnData = nullptr;
123         return;
124     }
125 }
126
127 WebConnection* InjectedBundle::webConnectionToUIProcess() const
128 {
129     return WebProcess::shared().webConnectionToUIProcess();
130 }
131
132 void InjectedBundle::setShouldTrackVisitedLinks(bool shouldTrackVisitedLinks)
133 {
134     WebProcess::shared().setShouldTrackVisitedLinks(shouldTrackVisitedLinks);
135 }
136
137 void InjectedBundle::setAlwaysAcceptCookies(bool accept)
138 {
139     WebProcess::shared().supplement<WebCookieManager>()->setHTTPCookieAcceptPolicy(accept ? HTTPCookieAcceptPolicyAlways : HTTPCookieAcceptPolicyOnlyFromMainDocumentDomain);
140 }
141
142 void InjectedBundle::removeAllVisitedLinks()
143 {
144     PageGroup::removeAllVisitedLinks();
145 }
146
147 void InjectedBundle::setCacheModel(uint32_t cacheModel)
148 {
149     WebProcess::shared().setCacheModel(cacheModel);
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 (HashSet<Page*>::iterator i = pages.begin(); i != pages.end(); ++i) {
159             WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient((*i)->mainFrame().loader().client());
160             ASSERT(webFrameLoaderClient);
161             webFrameLoaderClient->webFrame()->page()->setTabToLinksEnabled(enabled);
162         }
163     }
164
165     if (preference == "WebKit2AsynchronousPluginInitializationEnabled") {
166         WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledKey(), enabled);
167         for (HashSet<Page*>::iterator i = pages.begin(); i != pages.end(); ++i) {
168             WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient((*i)->mainFrame().loader().client());
169             ASSERT(webFrameLoaderClient);
170             webFrameLoaderClient->webFrame()->page()->setAsynchronousPluginInitializationEnabled(enabled);
171         }
172     }
173
174     if (preference == "WebKit2AsynchronousPluginInitializationEnabledForAllPlugins") {
175         WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledForAllPluginsKey(), enabled);
176         for (HashSet<Page*>::iterator i = pages.begin(); i != pages.end(); ++i) {
177             WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient((*i)->mainFrame().loader().client());
178             ASSERT(webFrameLoaderClient);
179             webFrameLoaderClient->webFrame()->page()->setAsynchronousPluginInitializationEnabledForAllPlugins(enabled);
180         }
181     }
182
183     if (preference == "WebKit2ArtificialPluginInitializationDelayEnabled") {
184         WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::artificialPluginInitializationDelayEnabledKey(), enabled);
185         for (HashSet<Page*>::iterator i = pages.begin(); i != pages.end(); ++i) {
186             WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient((*i)->mainFrame().loader().client());
187             ASSERT(webFrameLoaderClient);
188             webFrameLoaderClient->webFrame()->page()->setArtificialPluginInitializationDelayEnabled(enabled);
189         }
190     }
191
192 #if ENABLE(CSS_REGIONS)
193     if (preference == "WebKitCSSRegionsEnabled")
194         RuntimeEnabledFeatures::sharedFeatures().setCSSRegionsEnabled(enabled);
195 #endif
196
197 #if ENABLE(CSS_COMPOSITING)
198     if (preference == "WebKitCSSCompositingEnabled")
199         RuntimeEnabledFeatures::sharedFeatures().setCSSCompositingEnabled(enabled);
200 #endif
201
202     // Map the names used in LayoutTests with the names used in WebCore::Settings and WebPreferencesStore.
203 #define FOR_EACH_OVERRIDE_BOOL_PREFERENCE(macro) \
204     macro(WebKitAcceleratedCompositingEnabled, AcceleratedCompositingEnabled, acceleratedCompositingEnabled) \
205     macro(WebKitCanvasUsesAcceleratedDrawing, CanvasUsesAcceleratedDrawing, canvasUsesAcceleratedDrawing) \
206     macro(WebKitCSSCustomFilterEnabled, CSSCustomFilterEnabled, cssCustomFilterEnabled) \
207     macro(WebKitCSSGridLayoutEnabled, CSSGridLayoutEnabled, cssGridLayoutEnabled) \
208     macro(WebKitFrameFlatteningEnabled, FrameFlatteningEnabled, frameFlatteningEnabled) \
209     macro(WebKitJavaEnabled, JavaEnabled, javaEnabled) \
210     macro(WebKitJavaScriptEnabled, ScriptEnabled, javaScriptEnabled) \
211     macro(WebKitLoadSiteIconsKey, LoadsSiteIconsIgnoringImageLoadingSetting, loadsSiteIconsIgnoringImageLoadingPreference) \
212     macro(WebKitOfflineWebApplicationCacheEnabled, OfflineWebApplicationCacheEnabled, offlineWebApplicationCacheEnabled) \
213     macro(WebKitPageCacheSupportsPluginsPreferenceKey, PageCacheSupportsPlugins, pageCacheSupportsPlugins) \
214     macro(WebKitPluginsEnabled, PluginsEnabled, pluginsEnabled) \
215     macro(WebKitUsesPageCachePreferenceKey, UsesPageCache, usesPageCache) \
216     macro(WebKitWebAudioEnabled, WebAudioEnabled, webAudioEnabled) \
217     macro(WebKitWebGLEnabled, WebGLEnabled, webGLEnabled) \
218     macro(WebKitXSSAuditorEnabled, XSSAuditorEnabled, xssAuditorEnabled) \
219     macro(WebKitShouldRespectImageOrientation, ShouldRespectImageOrientation, shouldRespectImageOrientation) \
220     macro(WebKitEnableCaretBrowsing, CaretBrowsingEnabled, caretBrowsingEnabled) \
221     macro(WebKitDisplayImagesKey, LoadsImagesAutomatically, loadsImagesAutomatically)
222
223     if (preference == "WebKitAcceleratedCompositingEnabled")
224         enabled = enabled && LayerTreeHost::supportsAcceleratedCompositing();
225
226 #define OVERRIDE_PREFERENCE_AND_SET_IN_EXISTING_PAGES(TestRunnerName, SettingsName, WebPreferencesName) \
227     if (preference == #TestRunnerName) { \
228         WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::WebPreferencesName##Key(), enabled); \
229         for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter) \
230             (*iter)->settings().set##SettingsName(enabled); \
231         return; \
232     }
233
234     FOR_EACH_OVERRIDE_BOOL_PREFERENCE(OVERRIDE_PREFERENCE_AND_SET_IN_EXISTING_PAGES)
235
236 #if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
237     OVERRIDE_PREFERENCE_AND_SET_IN_EXISTING_PAGES(WebKitHiddenPageDOMTimerThrottlingEnabled, HiddenPageDOMTimerThrottlingEnabled, hiddenPageDOMTimerThrottlingEnabled)
238 #endif
239
240 #undef OVERRIDE_PREFERENCE_AND_SET_IN_EXISTING_PAGES
241 #undef FOR_EACH_OVERRIDE_BOOL_PREFERENCE
242 }
243
244 void InjectedBundle::overrideXSSAuditorEnabledForTestRunner(WebPageGroupProxy* pageGroup, bool enabled)
245 {
246     // Override the preference for all future pages.
247     WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey(), enabled);
248
249     // Change the setting for existing ones.
250     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
251     for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
252         (*iter)->settings().setXSSAuditorEnabled(enabled);
253 }
254
255 void InjectedBundle::setAllowUniversalAccessFromFileURLs(WebPageGroupProxy* pageGroup, bool enabled)
256 {
257     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
258     for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
259         (*iter)->settings().setAllowUniversalAccessFromFileURLs(enabled);
260 }
261
262 void InjectedBundle::setAllowFileAccessFromFileURLs(WebPageGroupProxy* pageGroup, bool enabled)
263 {
264     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
265     for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
266         (*iter)->settings().setAllowFileAccessFromFileURLs(enabled);
267 }
268
269 void InjectedBundle::setMinimumLogicalFontSize(WebPageGroupProxy* pageGroup, int size)
270 {
271     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
272     for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
273         (*iter)->settings().setMinimumLogicalFontSize(size);
274 }
275
276 void InjectedBundle::setFrameFlatteningEnabled(WebPageGroupProxy* pageGroup, bool enabled)
277 {
278     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
279     for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
280         (*iter)->settings().setFrameFlatteningEnabled(enabled);
281 }
282
283 void InjectedBundle::setPluginsEnabled(WebPageGroupProxy* pageGroup, bool enabled)
284 {
285     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
286     for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
287         (*iter)->settings().setPluginsEnabled(enabled);
288 }
289
290 void InjectedBundle::setJavaScriptCanAccessClipboard(WebPageGroupProxy* pageGroup, bool enabled)
291 {
292     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
293     for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
294         (*iter)->settings().setJavaScriptCanAccessClipboard(enabled);
295 }
296
297 void InjectedBundle::setPrivateBrowsingEnabled(WebPageGroupProxy* pageGroup, bool enabled)
298 {
299     // FIXME (NetworkProcess): This test-only function doesn't work with NetworkProcess, <https://bugs.webkit.org/show_bug.cgi?id=115274>.
300 #if PLATFORM(MAC) || USE(CFNETWORK) || USE(SOUP)
301     if (enabled)
302         WebFrameNetworkingContext::ensurePrivateBrowsingSession();
303     else
304         WebFrameNetworkingContext::destroyPrivateBrowsingSession();
305 #endif
306     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
307     for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
308         (*iter)->settings().setPrivateBrowsingEnabled(enabled);
309 }
310
311 void InjectedBundle::setPopupBlockingEnabled(WebPageGroupProxy* pageGroup, bool enabled)
312 {
313     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
314     HashSet<Page*>::const_iterator end = pages.end();
315     for (HashSet<Page*>::const_iterator iter = pages.begin(); iter != end; ++iter)
316         (*iter)->settings().setJavaScriptCanOpenWindowsAutomatically(!enabled);
317 }
318
319 void InjectedBundle::setAuthorAndUserStylesEnabled(WebPageGroupProxy* pageGroup, bool enabled)
320 {
321     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
322     for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
323         (*iter)->settings().setAuthorAndUserStylesEnabled(enabled);
324 }
325
326 void InjectedBundle::setSpatialNavigationEnabled(WebPageGroupProxy* pageGroup, bool enabled)
327 {
328     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
329     for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
330         (*iter)->settings().setSpatialNavigationEnabled(enabled);
331 }
332
333 void InjectedBundle::addOriginAccessWhitelistEntry(const String& sourceOrigin, const String& destinationProtocol, const String& destinationHost, bool allowDestinationSubdomains)
334 {
335     SecurityPolicy::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
336 }
337
338 void InjectedBundle::removeOriginAccessWhitelistEntry(const String& sourceOrigin, const String& destinationProtocol, const String& destinationHost, bool allowDestinationSubdomains)
339 {
340     SecurityPolicy::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains);
341 }
342
343 void InjectedBundle::resetOriginAccessWhitelists()
344 {
345     SecurityPolicy::resetOriginAccessWhitelists();
346 }
347
348 void InjectedBundle::setAsynchronousSpellCheckingEnabled(WebPageGroupProxy* pageGroup, bool enabled)
349 {
350     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
351     for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
352         (*iter)->settings().setAsynchronousSpellCheckingEnabled(enabled);
353 }
354
355 void InjectedBundle::clearAllDatabases()
356 {
357 #if ENABLE(SQL_DATABASE)
358     WebProcess::shared().supplement<WebDatabaseManager>()->deleteAllDatabases();
359 #endif
360 }
361
362 void InjectedBundle::setDatabaseQuota(uint64_t quota)
363 {
364 #if ENABLE(SQL_DATABASE)
365     // Historically, we've used the following (somewhat non-sensical) string
366     // for the databaseIdentifier of local files.
367     WebProcess::shared().supplement<WebDatabaseManager>()->setQuotaForOrigin("file__0", quota);
368 #endif
369 }
370
371 void InjectedBundle::clearApplicationCache()
372 {
373     WebProcess::shared().supplement<WebApplicationCacheManager>()->deleteAllEntries();
374 }
375
376 void InjectedBundle::clearApplicationCacheForOrigin(const String& originString)
377 {
378     RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromString(originString);
379     ApplicationCache::deleteCacheForOrigin(origin.get());
380 }
381
382 void InjectedBundle::setAppCacheMaximumSize(uint64_t size)
383 {
384     WebProcess::shared().supplement<WebApplicationCacheManager>()->setAppCacheMaximumSize(size);
385 }
386
387 uint64_t InjectedBundle::appCacheUsageForOrigin(const String& originString)
388 {
389     RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromString(originString);
390     return ApplicationCache::diskUsageForOrigin(origin.get());
391 }
392
393 void InjectedBundle::setApplicationCacheOriginQuota(const String& originString, uint64_t bytes)
394 {
395     RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromString(originString);
396     cacheStorage().storeUpdatedQuotaForOrigin(origin.get(), bytes);
397 }
398
399 void InjectedBundle::resetApplicationCacheOriginQuota(const String& originString)
400 {
401     RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromString(originString);
402     cacheStorage().storeUpdatedQuotaForOrigin(origin.get(), cacheStorage().defaultOriginQuota());
403 }
404
405 PassRefPtr<ImmutableArray> InjectedBundle::originsWithApplicationCache()
406 {
407     HashSet<RefPtr<SecurityOrigin>> origins;
408     cacheStorage().getOriginsWithCache(origins);
409     Vector< RefPtr<APIObject>> originsVector;
410
411     HashSet<RefPtr<SecurityOrigin>>::iterator it = origins.begin();
412     HashSet<RefPtr<SecurityOrigin>>::iterator end = origins.end();
413     for ( ; it != end; ++it)
414         originsVector.append(WebString::create((*it)->databaseIdentifier()));
415
416     return ImmutableArray::adopt(originsVector);
417 }
418
419 int InjectedBundle::numberOfPages(WebFrame* frame, double pageWidthInPixels, double pageHeightInPixels)
420 {
421     Frame* coreFrame = frame ? frame->coreFrame() : 0;
422     if (!coreFrame)
423         return -1;
424     if (!pageWidthInPixels)
425         pageWidthInPixels = coreFrame->view()->width();
426     if (!pageHeightInPixels)
427         pageHeightInPixels = coreFrame->view()->height();
428
429     return PrintContext::numberOfPages(coreFrame, FloatSize(pageWidthInPixels, pageHeightInPixels));
430 }
431
432 int InjectedBundle::pageNumberForElementById(WebFrame* frame, const String& id, double pageWidthInPixels, double pageHeightInPixels)
433 {
434     Frame* coreFrame = frame ? frame->coreFrame() : 0;
435     if (!coreFrame)
436         return -1;
437
438     Element* element = coreFrame->document()->getElementById(AtomicString(id));
439     if (!element)
440         return -1;
441
442     if (!pageWidthInPixels)
443         pageWidthInPixels = coreFrame->view()->width();
444     if (!pageHeightInPixels)
445         pageHeightInPixels = coreFrame->view()->height();
446
447     return PrintContext::pageNumberForElement(element, FloatSize(pageWidthInPixels, pageHeightInPixels));
448 }
449
450 String InjectedBundle::pageSizeAndMarginsInPixels(WebFrame* frame, int pageIndex, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft)
451 {
452     Frame* coreFrame = frame ? frame->coreFrame() : 0;
453     if (!coreFrame)
454         return String();
455
456     return PrintContext::pageSizeAndMarginsInPixels(coreFrame, pageIndex, width, height, marginTop, marginRight, marginBottom, marginLeft);
457 }
458
459 bool InjectedBundle::isPageBoxVisible(WebFrame* frame, int pageIndex)
460 {
461     Frame* coreFrame = frame ? frame->coreFrame() : 0;
462     if (!coreFrame)
463         return false;
464
465     return PrintContext::isPageBoxVisible(coreFrame, pageIndex);
466 }
467
468 bool InjectedBundle::isProcessingUserGesture()
469 {
470     return ScriptController::processingUserGesture();
471 }
472
473 static Vector<String> toStringVector(ImmutableArray* patterns)
474 {
475     Vector<String> patternsVector;
476
477     if (!patterns)
478         return patternsVector;
479
480     size_t size = patterns->size();
481     if (!size)
482         return patternsVector;
483
484     patternsVector.reserveInitialCapacity(size);
485     for (size_t i = 0; i < size; ++i) {
486         WebString* entry = patterns->at<WebString>(i);
487         if (entry)
488             patternsVector.uncheckedAppend(entry->string());
489     }
490     return patternsVector;
491 }
492
493 void InjectedBundle::addUserScript(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld, const String& source, const String& url, ImmutableArray* whitelist, ImmutableArray* blacklist, WebCore::UserScriptInjectionTime injectionTime, WebCore::UserContentInjectedFrames injectedFrames)
494 {
495     // url is not from KURL::string(), i.e. it has not already been parsed by KURL, so we have to use the relative URL constructor for KURL instead of the ParsedURLStringTag version.
496     PageGroup::pageGroup(pageGroup->identifier())->addUserScriptToWorld(scriptWorld->coreWorld(), source, KURL(KURL(), url), toStringVector(whitelist), toStringVector(blacklist), injectionTime, injectedFrames);
497 }
498
499 void InjectedBundle::addUserStyleSheet(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld, const String& source, const String& url, ImmutableArray* whitelist, ImmutableArray* blacklist, WebCore::UserContentInjectedFrames injectedFrames)
500 {
501     // url is not from KURL::string(), i.e. it has not already been parsed by KURL, so we have to use the relative URL constructor for KURL instead of the ParsedURLStringTag version.
502     PageGroup::pageGroup(pageGroup->identifier())->addUserStyleSheetToWorld(scriptWorld->coreWorld(), source, KURL(KURL(), url), toStringVector(whitelist), toStringVector(blacklist), injectedFrames);
503 }
504
505 void InjectedBundle::removeUserScript(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld, const String& url)
506 {
507     // url is not from KURL::string(), i.e. it has not already been parsed by KURL, so we have to use the relative URL constructor for KURL instead of the ParsedURLStringTag version.
508     PageGroup::pageGroup(pageGroup->identifier())->removeUserScriptFromWorld(scriptWorld->coreWorld(), KURL(KURL(), url));
509 }
510
511 void InjectedBundle::removeUserStyleSheet(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld, const String& url)
512 {
513     // url is not from KURL::string(), i.e. it has not already been parsed by KURL, so we have to use the relative URL constructor for KURL instead of the ParsedURLStringTag version.
514     PageGroup::pageGroup(pageGroup->identifier())->removeUserStyleSheetFromWorld(scriptWorld->coreWorld(), KURL(KURL(), url));
515 }
516
517 void InjectedBundle::removeUserScripts(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld)
518 {
519     PageGroup::pageGroup(pageGroup->identifier())->removeUserScriptsFromWorld(scriptWorld->coreWorld());
520 }
521
522 void InjectedBundle::removeUserStyleSheets(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld)
523 {
524     PageGroup::pageGroup(pageGroup->identifier())->removeUserStyleSheetsFromWorld(scriptWorld->coreWorld());
525 }
526
527 void InjectedBundle::removeAllUserContent(WebPageGroupProxy* pageGroup)
528 {
529     PageGroup::pageGroup(pageGroup->identifier())->removeAllUserContent();
530 }
531
532 void InjectedBundle::garbageCollectJavaScriptObjects()
533 {
534     gcController().garbageCollectNow();
535 }
536
537 void InjectedBundle::garbageCollectJavaScriptObjectsOnAlternateThreadForDebugging(bool waitUntilDone)
538 {
539     gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone);
540 }
541
542 size_t InjectedBundle::javaScriptObjectsCount()
543 {
544     JSLockHolder lock(JSDOMWindow::commonVM());
545     return JSDOMWindow::commonVM()->heap.objectCount();
546 }
547
548 void InjectedBundle::reportException(JSContextRef context, JSValueRef exception)
549 {
550     if (!context || !exception)
551         return;
552
553     JSC::ExecState* execState = toJS(context);
554     JSLockHolder lock(execState);
555
556     // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a Page.
557     if (!toJSDOMWindow(execState->lexicalGlobalObject()))
558         return;
559
560     WebCore::reportException(execState, toJS(execState, exception));
561 }
562
563 void InjectedBundle::didCreatePage(WebPage* page)
564 {
565     m_client.didCreatePage(this, page);
566 }
567
568 void InjectedBundle::willDestroyPage(WebPage* page)
569 {
570     m_client.willDestroyPage(this, page);
571 }
572
573 void InjectedBundle::didInitializePageGroup(WebPageGroupProxy* pageGroup)
574 {
575     m_client.didInitializePageGroup(this, pageGroup);
576 }
577
578 void InjectedBundle::didReceiveMessage(const String& messageName, APIObject* messageBody)
579 {
580     m_client.didReceiveMessage(this, messageName, messageBody);
581 }
582
583 void InjectedBundle::didReceiveMessageToPage(WebPage* page, const String& messageName, APIObject* messageBody)
584 {
585     m_client.didReceiveMessageToPage(this, page, messageName, messageBody);
586 }
587
588 void InjectedBundle::setUserStyleSheetLocation(WebPageGroupProxy* pageGroup, const String& location)
589 {
590     const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
591     for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
592         (*iter)->settings().setUserStyleSheetLocation(KURL(KURL(), location));
593 }
594
595 void InjectedBundle::setWebNotificationPermission(WebPage* page, const String& originString, bool allowed)
596 {
597 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
598     page->notificationPermissionRequestManager()->setPermissionLevelForTesting(originString, allowed);
599 #else
600     UNUSED_PARAM(page);
601     UNUSED_PARAM(originString);
602     UNUSED_PARAM(allowed);
603 #endif
604 }
605
606 void InjectedBundle::removeAllWebNotificationPermissions(WebPage* page)
607 {
608 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
609     page->notificationPermissionRequestManager()->removeAllPermissionsForTesting();
610 #else
611     UNUSED_PARAM(page);
612 #endif
613 }
614
615 uint64_t InjectedBundle::webNotificationID(JSContextRef jsContext, JSValueRef jsNotification)
616 {
617 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
618     WebCore::Notification* notification = toNotification(toJS(toJS(jsContext), jsNotification));
619     if (!notification)
620         return 0;
621     return WebProcess::shared().supplement<WebNotificationManager>()->notificationIDForTesting(notification);
622 #else
623     UNUSED_PARAM(jsContext);
624     UNUSED_PARAM(jsNotification);
625     return 0;
626 #endif
627 }
628
629 PassRefPtr<WebData> InjectedBundle::createWebDataFromUint8Array(JSContextRef context, JSValueRef data)
630 {
631     JSC::ExecState* execState = toJS(context);
632     RefPtr<Uint8Array> arrayData = WebCore::toUint8Array(toJS(execState, data));
633     return WebData::create(static_cast<unsigned char*>(arrayData->baseAddress()), arrayData->byteLength());
634 }
635
636 void InjectedBundle::setTabKeyCyclesThroughElements(WebPage* page, bool enabled)
637 {
638     page->corePage()->setTabKeyCyclesThroughElements(enabled);
639 }
640
641 void InjectedBundle::setSerialLoadingEnabled(bool enabled)
642 {
643     resourceLoadScheduler()->setSerialLoadingEnabled(enabled);
644 }
645
646 void InjectedBundle::setShadowDOMEnabled(bool enabled)
647 {
648 #if ENABLE(SHADOW_DOM)
649     RuntimeEnabledFeatures::sharedFeatures().setShadowDOMEnabled(enabled);
650 #else
651     UNUSED_PARAM(enabled);
652 #endif
653 }
654
655 void InjectedBundle::setCSSRegionsEnabled(bool enabled)
656 {
657 #if ENABLE(CSS_REGIONS)
658     RuntimeEnabledFeatures::sharedFeatures().setCSSRegionsEnabled(enabled);
659 #else
660     UNUSED_PARAM(enabled);
661 #endif
662 }
663
664 void InjectedBundle::setCSSCompositingEnabled(bool enabled)
665 {
666 #if ENABLE(CSS_COMPOSITING)
667     RuntimeEnabledFeatures::sharedFeatures().setCSSCompositingEnabled(enabled);
668 #else
669     UNUSED_PARAM(enabled);
670 #endif
671 }
672
673 void InjectedBundle::setSeamlessIFramesEnabled(bool enabled)
674 {
675 #if ENABLE(IFRAME_SEAMLESS)
676     RuntimeEnabledFeatures::sharedFeatures().setSeamlessIFramesEnabled(enabled);
677 #else
678     UNUSED_PARAM(enabled);
679 #endif
680 }
681
682 void InjectedBundle::dispatchPendingLoadRequests()
683 {
684     resourceLoadScheduler()->servePendingRequests();
685 }
686
687 } // namespace WebKit