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 "APIArray.h"
30#include "Arguments.h"
31#include "InjectedBundleScriptWorld.h"
32#include "InjectedBundleUserMessageCoders.h"
33#include "NotificationPermissionRequestManager.h"
34#include "SessionTracker.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 "WebDatabaseManager.h"
43#include "WebFrame.h"
44#include "WebFrameNetworkingContext.h"
45#include "WebPage.h"
46#include "WebPreferencesKeys.h"
47#include "WebPreferencesStore.h"
48#include "WebProcess.h"
49#include "WebProcessCreationParameters.h"
50#include <JavaScriptCore/APICast.h>
51#include <JavaScriptCore/JSLock.h>
52#include <WebCore/ApplicationCache.h>
53#include <WebCore/ApplicationCacheStorage.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/MainFrame.h>
63#include <WebCore/Page.h>
64#include <WebCore/PageGroup.h>
65#include <WebCore/PrintContext.h>
66#include <WebCore/ResourceHandle.h>
67#include <WebCore/ResourceLoadScheduler.h>
68#include <WebCore/ScriptController.h>
69#include <WebCore/SecurityOrigin.h>
70#include <WebCore/SecurityPolicy.h>
71#include <WebCore/SessionID.h>
72#include <WebCore/Settings.h>
73#include <WebCore/UserGestureIndicator.h>
74
75#if ENABLE(CSS_REGIONS) || ENABLE(CSS_COMPOSITING)
76#include <WebCore/RuntimeEnabledFeatures.h>
77#endif
78
79#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
80#include "WebNotificationManager.h"
81#endif
82
83using namespace WebCore;
84using namespace JSC;
85
86namespace WebKit {
87
88PassRefPtr<InjectedBundle> InjectedBundle::create(const WebProcessCreationParameters& parameters, API::Object* initializationUserData)
89{
90    RefPtr<InjectedBundle> bundle = adoptRef(new InjectedBundle(parameters));
91
92    bundle->m_sandboxExtension = SandboxExtension::create(parameters.injectedBundlePathExtensionHandle);
93    if (!bundle->initialize(parameters, initializationUserData))
94        return nullptr;
95
96    return bundle.release();
97}
98
99InjectedBundle::InjectedBundle(const WebProcessCreationParameters& parameters)
100    : m_path(parameters.injectedBundlePath)
101    , m_platformBundle(0)
102{
103}
104
105InjectedBundle::~InjectedBundle()
106{
107}
108
109void InjectedBundle::initializeClient(const WKBundleClientBase* client)
110{
111    m_client.initialize(client);
112}
113
114void InjectedBundle::postMessage(const String& messageName, API::Object* messageBody)
115{
116    auto encoder = std::make_unique<IPC::MessageEncoder>(WebContextLegacyMessages::messageReceiverName(), WebContextLegacyMessages::postMessageMessageName(), 0);
117    encoder->encode(messageName);
118    encoder->encode(InjectedBundleUserMessageEncoder(messageBody));
119
120    WebProcess::shared().parentProcessConnection()->sendMessage(WTF::move(encoder));
121}
122
123void InjectedBundle::postSynchronousMessage(const String& messageName, API::Object* messageBody, RefPtr<API::Object>& returnData)
124{
125    InjectedBundleUserMessageDecoder messageDecoder(returnData);
126
127    uint64_t syncRequestID;
128    std::unique_ptr<IPC::MessageEncoder> encoder = WebProcess::shared().parentProcessConnection()->createSyncMessageEncoder(WebContextLegacyMessages::messageReceiverName(), WebContextLegacyMessages::postSynchronousMessageMessageName(), 0, syncRequestID);
129    encoder->encode(messageName);
130    encoder->encode(InjectedBundleUserMessageEncoder(messageBody));
131
132    std::unique_ptr<IPC::MessageDecoder> replyDecoder = WebProcess::shared().parentProcessConnection()->sendSyncMessage(syncRequestID, WTF::move(encoder), std::chrono::milliseconds::max());
133    if (!replyDecoder || !replyDecoder->decode(messageDecoder)) {
134        returnData = nullptr;
135        return;
136    }
137}
138
139WebConnection* InjectedBundle::webConnectionToUIProcess() const
140{
141    return WebProcess::shared().webConnectionToUIProcess();
142}
143
144void InjectedBundle::setAlwaysAcceptCookies(bool accept)
145{
146    WebProcess::shared().supplement<WebCookieManager>()->setHTTPCookieAcceptPolicy(accept ? HTTPCookieAcceptPolicyAlways : HTTPCookieAcceptPolicyOnlyFromMainDocumentDomain);
147}
148
149void InjectedBundle::removeAllVisitedLinks()
150{
151    PageGroup::removeAllVisitedLinks();
152}
153
154void InjectedBundle::setCacheModel(uint32_t cacheModel)
155{
156    WebProcess::shared().setCacheModel(cacheModel);
157}
158
159void InjectedBundle::overrideBoolPreferenceForTestRunner(WebPageGroupProxy* pageGroup, const String& preference, bool enabled)
160{
161    const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
162
163    if (preference == "WebKitTabToLinksPreferenceKey") {
164        WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::tabsToLinksKey(), enabled);
165        for (auto* page : pages)
166            WebPage::fromCorePage(page)->setTabToLinksEnabled(enabled);
167    }
168
169    if (preference == "WebKit2AsynchronousPluginInitializationEnabled") {
170        WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledKey(), enabled);
171        for (auto* page : pages)
172            WebPage::fromCorePage(page)->setAsynchronousPluginInitializationEnabled(enabled);
173    }
174
175    if (preference == "WebKit2AsynchronousPluginInitializationEnabledForAllPlugins") {
176        WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledForAllPluginsKey(), enabled);
177        for (auto* page : pages)
178            WebPage::fromCorePage(page)->setAsynchronousPluginInitializationEnabledForAllPlugins(enabled);
179    }
180
181    if (preference == "WebKit2ArtificialPluginInitializationDelayEnabled") {
182        WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::artificialPluginInitializationDelayEnabledKey(), enabled);
183        for (auto* page : pages)
184            WebPage::fromCorePage(page)->setArtificialPluginInitializationDelayEnabled(enabled);
185    }
186
187#if ENABLE(SERVICE_CONTROLS)
188    if (preference == "WebKitImageControlsEnabled") {
189        WebPreferencesStore::overrideBoolValueForKey(WebPreferencesKey::imageControlsEnabledKey(), enabled);
190        for (auto* page : pages)
191            page->settings().setImageControlsEnabled(enabled);
192        return;
193    }
194#endif
195
196#if ENABLE(CSS_REGIONS)
197    if (preference == "WebKitCSSRegionsEnabled")
198        RuntimeEnabledFeatures::sharedFeatures().setCSSRegionsEnabled(enabled);
199#endif
200
201#if ENABLE(CSS_COMPOSITING)
202    if (preference == "WebKitCSSCompositingEnabled")
203        RuntimeEnabledFeatures::sharedFeatures().setCSSCompositingEnabled(enabled);
204#endif
205
206    // Map the names used in LayoutTests with the names used in WebCore::Settings and WebPreferencesStore.
207#define FOR_EACH_OVERRIDE_BOOL_PREFERENCE(macro) \
208    macro(WebKitAcceleratedCompositingEnabled, AcceleratedCompositingEnabled, acceleratedCompositingEnabled) \
209    macro(WebKitCanvasUsesAcceleratedDrawing, CanvasUsesAcceleratedDrawing, canvasUsesAcceleratedDrawing) \
210    macro(WebKitFrameFlatteningEnabled, FrameFlatteningEnabled, frameFlatteningEnabled) \
211    macro(WebKitJavaEnabled, JavaEnabled, javaEnabled) \
212    macro(WebKitJavaScriptEnabled, ScriptEnabled, javaScriptEnabled) \
213    macro(WebKitLoadSiteIconsKey, LoadsSiteIconsIgnoringImageLoadingSetting, loadsSiteIconsIgnoringImageLoadingPreference) \
214    macro(WebKitOfflineWebApplicationCacheEnabled, OfflineWebApplicationCacheEnabled, offlineWebApplicationCacheEnabled) \
215    macro(WebKitPageCacheSupportsPluginsPreferenceKey, PageCacheSupportsPlugins, pageCacheSupportsPlugins) \
216    macro(WebKitPluginsEnabled, PluginsEnabled, pluginsEnabled) \
217    macro(WebKitUsesPageCachePreferenceKey, UsesPageCache, usesPageCache) \
218    macro(WebKitWebAudioEnabled, WebAudioEnabled, webAudioEnabled) \
219    macro(WebKitWebGLEnabled, WebGLEnabled, webGLEnabled) \
220    macro(WebKitXSSAuditorEnabled, XSSAuditorEnabled, xssAuditorEnabled) \
221    macro(WebKitShouldRespectImageOrientation, ShouldRespectImageOrientation, shouldRespectImageOrientation) \
222    macro(WebKitEnableCaretBrowsing, CaretBrowsingEnabled, caretBrowsingEnabled) \
223    macro(WebKitDisplayImagesKey, LoadsImagesAutomatically, loadsImagesAutomatically) \
224    macro(WebKitMediaStreamEnabled, MediaStreamEnabled, mediaStreamEnabled)
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
244void 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
255void 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
262void 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
269void 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
276void 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
283void 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
290void 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
297void 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(COCOA) || USE(CFNETWORK) || USE(SOUP)
301    if (enabled)
302        WebFrameNetworkingContext::ensurePrivateBrowsingSession(SessionID::legacyPrivateSessionID());
303    else
304        SessionTracker::destroySession(SessionID::legacyPrivateSessionID());
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)->enableLegacyPrivateBrowsing(enabled);
309}
310
311void 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
319void 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
326void 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
333void 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
338void 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
343void InjectedBundle::resetOriginAccessWhitelists()
344{
345    SecurityPolicy::resetOriginAccessWhitelists();
346}
347
348void 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
355void InjectedBundle::clearAllDatabases()
356{
357#if ENABLE(SQL_DATABASE)
358    WebProcess::shared().supplement<WebDatabaseManager>()->deleteAllDatabases();
359#endif
360}
361
362void 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#else
369    UNUSED_PARAM(quota);
370#endif
371}
372
373void InjectedBundle::clearApplicationCache()
374{
375    WebProcess::shared().supplement<WebApplicationCacheManager>()->deleteAllEntries();
376}
377
378void InjectedBundle::clearApplicationCacheForOrigin(const String& originString)
379{
380    RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromString(originString);
381    ApplicationCache::deleteCacheForOrigin(origin.get());
382}
383
384void InjectedBundle::setAppCacheMaximumSize(uint64_t size)
385{
386    WebProcess::shared().supplement<WebApplicationCacheManager>()->setAppCacheMaximumSize(size);
387}
388
389uint64_t InjectedBundle::appCacheUsageForOrigin(const String& originString)
390{
391    RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromString(originString);
392    return ApplicationCache::diskUsageForOrigin(origin.get());
393}
394
395void InjectedBundle::setApplicationCacheOriginQuota(const String& originString, uint64_t bytes)
396{
397    RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromString(originString);
398    cacheStorage().storeUpdatedQuotaForOrigin(origin.get(), bytes);
399}
400
401void InjectedBundle::resetApplicationCacheOriginQuota(const String& originString)
402{
403    RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromString(originString);
404    cacheStorage().storeUpdatedQuotaForOrigin(origin.get(), cacheStorage().defaultOriginQuota());
405}
406
407PassRefPtr<API::Array> InjectedBundle::originsWithApplicationCache()
408{
409    HashSet<RefPtr<SecurityOrigin>> origins;
410    cacheStorage().getOriginsWithCache(origins);
411
412    Vector<RefPtr<API::Object>> originIdentifiers;
413    originIdentifiers.reserveInitialCapacity(origins.size());
414
415    for (const auto& origin : origins)
416        originIdentifiers.uncheckedAppend(API::String::create(origin->databaseIdentifier()));
417
418    return API::Array::create(WTF::move(originIdentifiers));
419}
420
421int InjectedBundle::numberOfPages(WebFrame* frame, double pageWidthInPixels, double pageHeightInPixels)
422{
423    Frame* coreFrame = frame ? frame->coreFrame() : 0;
424    if (!coreFrame)
425        return -1;
426    if (!pageWidthInPixels)
427        pageWidthInPixels = coreFrame->view()->width();
428    if (!pageHeightInPixels)
429        pageHeightInPixels = coreFrame->view()->height();
430
431    return PrintContext::numberOfPages(coreFrame, FloatSize(pageWidthInPixels, pageHeightInPixels));
432}
433
434int InjectedBundle::pageNumberForElementById(WebFrame* frame, const String& id, double pageWidthInPixels, double pageHeightInPixels)
435{
436    Frame* coreFrame = frame ? frame->coreFrame() : 0;
437    if (!coreFrame)
438        return -1;
439
440    Element* element = coreFrame->document()->getElementById(id);
441    if (!element)
442        return -1;
443
444    if (!pageWidthInPixels)
445        pageWidthInPixels = coreFrame->view()->width();
446    if (!pageHeightInPixels)
447        pageHeightInPixels = coreFrame->view()->height();
448
449    return PrintContext::pageNumberForElement(element, FloatSize(pageWidthInPixels, pageHeightInPixels));
450}
451
452String InjectedBundle::pageSizeAndMarginsInPixels(WebFrame* frame, int pageIndex, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft)
453{
454    Frame* coreFrame = frame ? frame->coreFrame() : 0;
455    if (!coreFrame)
456        return String();
457
458    return PrintContext::pageSizeAndMarginsInPixels(coreFrame, pageIndex, width, height, marginTop, marginRight, marginBottom, marginLeft);
459}
460
461bool InjectedBundle::isPageBoxVisible(WebFrame* frame, int pageIndex)
462{
463    Frame* coreFrame = frame ? frame->coreFrame() : 0;
464    if (!coreFrame)
465        return false;
466
467    return PrintContext::isPageBoxVisible(coreFrame, pageIndex);
468}
469
470bool InjectedBundle::isProcessingUserGesture()
471{
472    return ScriptController::processingUserGesture();
473}
474
475void InjectedBundle::addUserScript(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld, const String& source, const String& url, API::Array* whitelist, API::Array* blacklist, WebCore::UserScriptInjectionTime injectionTime, WebCore::UserContentInjectedFrames injectedFrames)
476{
477    // 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.
478    PageGroup::pageGroup(pageGroup->identifier())->addUserScriptToWorld(scriptWorld->coreWorld(), source, URL(URL(), url), whitelist ? whitelist->toStringVector() : Vector<String>(), blacklist ? blacklist->toStringVector() : Vector<String>(), injectionTime, injectedFrames);
479}
480
481void InjectedBundle::addUserStyleSheet(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld, const String& source, const String& url, API::Array* whitelist, API::Array* blacklist, WebCore::UserContentInjectedFrames injectedFrames)
482{
483    // 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.
484    PageGroup::pageGroup(pageGroup->identifier())->addUserStyleSheetToWorld(scriptWorld->coreWorld(), source, URL(URL(), url), whitelist ? whitelist->toStringVector() : Vector<String>(), blacklist ? blacklist->toStringVector() : Vector<String>(), injectedFrames);
485}
486
487void InjectedBundle::removeUserScript(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld, const String& url)
488{
489    // 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.
490    PageGroup::pageGroup(pageGroup->identifier())->removeUserScriptFromWorld(scriptWorld->coreWorld(), URL(URL(), url));
491}
492
493void InjectedBundle::removeUserStyleSheet(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld, const String& url)
494{
495    // 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.
496    PageGroup::pageGroup(pageGroup->identifier())->removeUserStyleSheetFromWorld(scriptWorld->coreWorld(), URL(URL(), url));
497}
498
499void InjectedBundle::removeUserScripts(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld)
500{
501    PageGroup::pageGroup(pageGroup->identifier())->removeUserScriptsFromWorld(scriptWorld->coreWorld());
502}
503
504void InjectedBundle::removeUserStyleSheets(WebPageGroupProxy* pageGroup, InjectedBundleScriptWorld* scriptWorld)
505{
506    PageGroup::pageGroup(pageGroup->identifier())->removeUserStyleSheetsFromWorld(scriptWorld->coreWorld());
507}
508
509void InjectedBundle::removeAllUserContent(WebPageGroupProxy* pageGroup)
510{
511    PageGroup::pageGroup(pageGroup->identifier())->removeAllUserContent();
512}
513
514void InjectedBundle::garbageCollectJavaScriptObjects()
515{
516    gcController().garbageCollectNow();
517}
518
519void InjectedBundle::garbageCollectJavaScriptObjectsOnAlternateThreadForDebugging(bool waitUntilDone)
520{
521    gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone);
522}
523
524size_t InjectedBundle::javaScriptObjectsCount()
525{
526    JSLockHolder lock(JSDOMWindow::commonVM());
527    return JSDOMWindow::commonVM().heap.objectCount();
528}
529
530void InjectedBundle::reportException(JSContextRef context, JSValueRef exception)
531{
532    if (!context || !exception)
533        return;
534
535    JSC::ExecState* execState = toJS(context);
536    JSLockHolder lock(execState);
537
538    // Make sure the context has a DOMWindow global object, otherwise this context didn't originate from a Page.
539    if (!toJSDOMWindow(execState->lexicalGlobalObject()))
540        return;
541
542    WebCore::reportException(execState, toJS(execState, exception));
543}
544
545void InjectedBundle::didCreatePage(WebPage* page)
546{
547    m_client.didCreatePage(this, page);
548}
549
550void InjectedBundle::willDestroyPage(WebPage* page)
551{
552    m_client.willDestroyPage(this, page);
553}
554
555void InjectedBundle::didInitializePageGroup(WebPageGroupProxy* pageGroup)
556{
557    m_client.didInitializePageGroup(this, pageGroup);
558}
559
560void InjectedBundle::didReceiveMessage(const String& messageName, API::Object* messageBody)
561{
562    m_client.didReceiveMessage(this, messageName, messageBody);
563}
564
565void InjectedBundle::didReceiveMessageToPage(WebPage* page, const String& messageName, API::Object* messageBody)
566{
567    m_client.didReceiveMessageToPage(this, page, messageName, messageBody);
568}
569
570void InjectedBundle::setUserStyleSheetLocation(WebPageGroupProxy* pageGroup, const String& location)
571{
572    const HashSet<Page*>& pages = PageGroup::pageGroup(pageGroup->identifier())->pages();
573    for (HashSet<Page*>::iterator iter = pages.begin(); iter != pages.end(); ++iter)
574        (*iter)->settings().setUserStyleSheetLocation(URL(URL(), location));
575}
576
577void InjectedBundle::setWebNotificationPermission(WebPage* page, const String& originString, bool allowed)
578{
579#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
580    page->notificationPermissionRequestManager()->setPermissionLevelForTesting(originString, allowed);
581#else
582    UNUSED_PARAM(page);
583    UNUSED_PARAM(originString);
584    UNUSED_PARAM(allowed);
585#endif
586}
587
588void InjectedBundle::removeAllWebNotificationPermissions(WebPage* page)
589{
590#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
591    page->notificationPermissionRequestManager()->removeAllPermissionsForTesting();
592#else
593    UNUSED_PARAM(page);
594#endif
595}
596
597uint64_t InjectedBundle::webNotificationID(JSContextRef jsContext, JSValueRef jsNotification)
598{
599#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
600    WebCore::Notification* notification = toNotification(toJS(toJS(jsContext), jsNotification));
601    if (!notification)
602        return 0;
603    return WebProcess::shared().supplement<WebNotificationManager>()->notificationIDForTesting(notification);
604#else
605    UNUSED_PARAM(jsContext);
606    UNUSED_PARAM(jsNotification);
607    return 0;
608#endif
609}
610
611// FIXME Get rid of this function and move it into WKBundle.cpp.
612PassRefPtr<API::Data> InjectedBundle::createWebDataFromUint8Array(JSContextRef context, JSValueRef data)
613{
614    JSC::ExecState* execState = toJS(context);
615    RefPtr<Uint8Array> arrayData = WebCore::toUint8Array(toJS(execState, data));
616    return API::Data::create(static_cast<unsigned char*>(arrayData->baseAddress()), arrayData->byteLength());
617}
618
619void InjectedBundle::setTabKeyCyclesThroughElements(WebPage* page, bool enabled)
620{
621    page->corePage()->setTabKeyCyclesThroughElements(enabled);
622}
623
624void InjectedBundle::setSerialLoadingEnabled(bool enabled)
625{
626    resourceLoadScheduler()->setSerialLoadingEnabled(enabled);
627}
628
629void InjectedBundle::setCSSRegionsEnabled(bool enabled)
630{
631#if ENABLE(CSS_REGIONS)
632    RuntimeEnabledFeatures::sharedFeatures().setCSSRegionsEnabled(enabled);
633#else
634    UNUSED_PARAM(enabled);
635#endif
636}
637
638void InjectedBundle::setCSSCompositingEnabled(bool enabled)
639{
640#if ENABLE(CSS_COMPOSITING)
641    RuntimeEnabledFeatures::sharedFeatures().setCSSCompositingEnabled(enabled);
642#else
643    UNUSED_PARAM(enabled);
644#endif
645}
646
647void InjectedBundle::dispatchPendingLoadRequests()
648{
649    resourceLoadScheduler()->servePendingRequests();
650}
651
652} // namespace WebKit
653