1/*
2 * Copyright (C) 2010, 2011, 2012 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 "WKContextPrivate.h"
28
29#include "APIClient.h"
30#include "APIContextConfiguration.h"
31#include "APIDownloadClient.h"
32#include "APIHistoryClient.h"
33#include "APINavigationData.h"
34#include "APIURLRequest.h"
35#include "WKAPICast.h"
36#include "WKContextConfigurationRef.h"
37#include "WKRetainPtr.h"
38#include "WebContext.h"
39#include <wtf/PassRefPtr.h>
40#include <wtf/RefPtr.h>
41#include <wtf/text/WTFString.h>
42
43// Supplements
44#include "WebApplicationCacheManagerProxy.h"
45#include "WebCookieManagerProxy.h"
46#include "WebGeolocationManagerProxy.h"
47#include "WebKeyValueStorageManager.h"
48#include "WebMediaCacheManagerProxy.h"
49#include "WebNotificationManagerProxy.h"
50#include "WebOriginDataManagerProxy.h"
51#include "WebResourceCacheManagerProxy.h"
52#if ENABLE(SQL_DATABASE)
53#include "WebDatabaseManagerProxy.h"
54#endif
55#if ENABLE(BATTERY_STATUS)
56#include "WebBatteryManagerProxy.h"
57#endif
58
59namespace API {
60template<> struct ClientTraits<WKContextDownloadClientBase> {
61    typedef std::tuple<WKContextDownloadClientV0> Versions;
62};
63template<> struct ClientTraits<WKContextHistoryClientBase> {
64    typedef std::tuple<WKContextHistoryClientV0> Versions;
65};
66}
67
68using namespace WebCore;
69using namespace WebKit;
70
71WKTypeID WKContextGetTypeID()
72{
73    return toAPI(WebContext::APIType);
74}
75
76WKContextRef WKContextCreate()
77{
78    return WKContextCreateWithConfiguration(adoptWK(WKContextConfigurationCreate()).get());
79}
80
81WKContextRef WKContextCreateWithInjectedBundlePath(WKStringRef pathRef)
82{
83    auto configuration = adoptWK(WKContextConfigurationCreate());
84    WKContextConfigurationSetInjectedBundlePath(configuration.get(), pathRef);
85
86    return WKContextCreateWithConfiguration(configuration.get());
87}
88
89WKContextRef WKContextCreateWithConfiguration(WKContextConfigurationRef configuration)
90{
91    return toAPI(WebContext::create(toImpl(configuration)->webContextConfiguration()).leakRef());
92}
93
94void WKContextSetClient(WKContextRef contextRef, const WKContextClientBase* wkClient)
95{
96    toImpl(contextRef)->initializeClient(wkClient);
97}
98
99void WKContextSetInjectedBundleClient(WKContextRef contextRef, const WKContextInjectedBundleClientBase* wkClient)
100{
101    toImpl(contextRef)->initializeInjectedBundleClient(wkClient);
102}
103
104void WKContextSetHistoryClient(WKContextRef contextRef, const WKContextHistoryClientBase* wkClient)
105{
106    class HistoryClient final : public API::Client<WKContextHistoryClientBase>, public API::HistoryClient {
107    public:
108        explicit HistoryClient(const WKContextHistoryClientBase* client)
109        {
110            initialize(client);
111        }
112
113    private:
114        virtual void didNavigateWithNavigationData(WebContext* context, WebPageProxy* page, const WebNavigationDataStore& navigationDataStore, WebFrameProxy* frame) override
115        {
116            if (!m_client.didNavigateWithNavigationData)
117                return;
118
119            RefPtr<API::NavigationData> navigationData = API::NavigationData::create(navigationDataStore);
120            m_client.didNavigateWithNavigationData(toAPI(context), toAPI(page), toAPI(navigationData.get()), toAPI(frame), m_client.base.clientInfo);
121        }
122
123        virtual void didPerformClientRedirect(WebContext* context, WebPageProxy* page, const String& sourceURL, const String& destinationURL, WebFrameProxy* frame) override
124        {
125            if (!m_client.didPerformClientRedirect)
126                return;
127
128            m_client.didPerformClientRedirect(toAPI(context), toAPI(page), toURLRef(sourceURL.impl()), toURLRef(destinationURL.impl()), toAPI(frame), m_client.base.clientInfo);
129        }
130
131        virtual void didPerformServerRedirect(WebContext* context, WebPageProxy* page, const String& sourceURL, const String& destinationURL, WebFrameProxy* frame) override
132        {
133            if (!m_client.didPerformServerRedirect)
134                return;
135
136            m_client.didPerformServerRedirect(toAPI(context), toAPI(page), toURLRef(sourceURL.impl()), toURLRef(destinationURL.impl()), toAPI(frame), m_client.base.clientInfo);
137        }
138
139        virtual void didUpdateHistoryTitle(WebContext* context, WebPageProxy* page, const String& title, const String& url, WebFrameProxy* frame) override
140        {
141            if (!m_client.didUpdateHistoryTitle)
142                return;
143
144            m_client.didUpdateHistoryTitle(toAPI(context), toAPI(page), toAPI(title.impl()), toURLRef(url.impl()), toAPI(frame), m_client.base.clientInfo);
145        }
146
147        virtual void populateVisitedLinks(WebContext* context) override
148        {
149            if (!m_client.populateVisitedLinks)
150                return;
151
152            m_client.populateVisitedLinks(toAPI(context), m_client.base.clientInfo);
153        }
154
155        virtual bool addsVisitedLinks() const override
156        {
157            return m_client.populateVisitedLinks;
158        }
159    };
160
161    WebKit::WebContext& context = *toImpl(contextRef);
162    context.setHistoryClient(std::make_unique<HistoryClient>(wkClient));
163
164    bool addsVisitedLinks = context.historyClient().addsVisitedLinks();
165
166    for (auto& process : context.processes()) {
167        for (auto& page : process->pages())
168            page->setAddsVisitedLinks(addsVisitedLinks);
169    }
170}
171
172void WKContextSetDownloadClient(WKContextRef contextRef, const WKContextDownloadClientBase* wkClient)
173{
174    class DownloadClient final : public API::Client<WKContextDownloadClientBase>, public API::DownloadClient {
175    public:
176        explicit DownloadClient(const WKContextDownloadClientBase* client)
177        {
178            initialize(client);
179        }
180    private:
181        virtual void didStart(WebContext* webContext, DownloadProxy* downloadProxy) override
182        {
183            if (!m_client.didStart)
184                return;
185
186            m_client.didStart(toAPI(webContext), toAPI(downloadProxy), m_client.base.clientInfo);
187        }
188
189        virtual void didReceiveAuthenticationChallenge(WebContext* webContext, DownloadProxy* downloadProxy, AuthenticationChallengeProxy* authenticationChallengeProxy) override
190        {
191            if (!m_client.didReceiveAuthenticationChallenge)
192                return;
193
194            m_client.didReceiveAuthenticationChallenge(toAPI(webContext), toAPI(downloadProxy), toAPI(authenticationChallengeProxy), m_client.base.clientInfo);
195        }
196
197        virtual void didReceiveResponse(WebContext* webContext, DownloadProxy* downloadProxy, const ResourceResponse& response) override
198        {
199            if (!m_client.didReceiveResponse)
200                return;
201
202            m_client.didReceiveResponse(toAPI(webContext), toAPI(downloadProxy), toAPI(API::URLResponse::create(response).get()), m_client.base.clientInfo);
203        }
204
205        virtual void didReceiveData(WebContext* webContext, DownloadProxy* downloadProxy, uint64_t length) override
206        {
207            if (!m_client.didReceiveData)
208                return;
209
210            m_client.didReceiveData(toAPI(webContext), toAPI(downloadProxy), length, m_client.base.clientInfo);
211        }
212
213        virtual bool shouldDecodeSourceDataOfMIMEType(WebContext* webContext, DownloadProxy* downloadProxy, const String& mimeType) override
214        {
215            if (!m_client.shouldDecodeSourceDataOfMIMEType)
216                return true;
217
218            return m_client.shouldDecodeSourceDataOfMIMEType(toAPI(webContext), toAPI(downloadProxy), toAPI(mimeType.impl()), m_client.base.clientInfo);
219        }
220
221        virtual String decideDestinationWithSuggestedFilename(WebContext* webContext, DownloadProxy* downloadProxy, const String& filename, bool& allowOverwrite) override
222        {
223            if (!m_client.decideDestinationWithSuggestedFilename)
224                return String();
225
226            WKRetainPtr<WKStringRef> destination(AdoptWK, m_client.decideDestinationWithSuggestedFilename(toAPI(webContext), toAPI(downloadProxy), toAPI(filename.impl()), &allowOverwrite, m_client.base.clientInfo));
227            return toWTFString(destination.get());
228        }
229
230        virtual void didCreateDestination(WebContext* webContext, DownloadProxy* downloadProxy, const String& path) override
231        {
232            if (!m_client.didCreateDestination)
233                return;
234
235            m_client.didCreateDestination(toAPI(webContext), toAPI(downloadProxy), toAPI(path.impl()), m_client.base.clientInfo);
236        }
237
238        virtual void didFinish(WebContext* webContext, DownloadProxy* downloadProxy) override
239        {
240            if (!m_client.didFinish)
241                return;
242
243            m_client.didFinish(toAPI(webContext), toAPI(downloadProxy), m_client.base.clientInfo);
244        }
245
246        virtual void didFail(WebContext* webContext, DownloadProxy* downloadProxy, const ResourceError& error) override
247        {
248            if (!m_client.didFail)
249                return;
250
251            m_client.didFail(toAPI(webContext), toAPI(downloadProxy), toAPI(error), m_client.base.clientInfo);
252        }
253
254        virtual void didCancel(WebContext* webContext, DownloadProxy* downloadProxy) override
255        {
256            if (!m_client.didCancel)
257                return;
258
259            m_client.didCancel(toAPI(webContext), toAPI(downloadProxy), m_client.base.clientInfo);
260        }
261
262        virtual void processDidCrash(WebContext* webContext, DownloadProxy* downloadProxy) override
263        {
264            if (!m_client.processDidCrash)
265                return;
266
267            m_client.processDidCrash(toAPI(webContext), toAPI(downloadProxy), m_client.base.clientInfo);
268        }
269
270    };
271
272    toImpl(contextRef)->setDownloadClient(std::make_unique<DownloadClient>(wkClient));
273}
274
275void WKContextSetConnectionClient(WKContextRef contextRef, const WKContextConnectionClientBase* wkClient)
276{
277    toImpl(contextRef)->initializeConnectionClient(wkClient);
278}
279
280WKDownloadRef WKContextDownloadURLRequest(WKContextRef contextRef, const WKURLRequestRef requestRef)
281{
282    return toAPI(toImpl(contextRef)->download(0, toImpl(requestRef)->resourceRequest()));
283}
284
285void WKContextSetInitializationUserDataForInjectedBundle(WKContextRef contextRef,  WKTypeRef userDataRef)
286{
287    toImpl(contextRef)->setInjectedBundleInitializationUserData(toImpl(userDataRef));
288}
289
290void WKContextPostMessageToInjectedBundle(WKContextRef contextRef, WKStringRef messageNameRef, WKTypeRef messageBodyRef)
291{
292    toImpl(contextRef)->postMessageToInjectedBundle(toImpl(messageNameRef)->string(), toImpl(messageBodyRef));
293}
294
295void WKContextGetGlobalStatistics(WKContextStatistics* statistics)
296{
297    const WebContext::Statistics& webContextStatistics = WebContext::statistics();
298
299    statistics->wkViewCount = webContextStatistics.wkViewCount;
300    statistics->wkPageCount = webContextStatistics.wkPageCount;
301    statistics->wkFrameCount = webContextStatistics.wkFrameCount;
302}
303
304void WKContextAddVisitedLink(WKContextRef contextRef, WKStringRef visitedURL)
305{
306    String visitedURLString = toImpl(visitedURL)->string();
307    if (visitedURLString.isEmpty())
308        return;
309
310    toImpl(contextRef)->visitedLinkProvider().addVisitedLinkHash(visitedLinkHash(visitedURLString));
311}
312
313void WKContextSetCacheModel(WKContextRef contextRef, WKCacheModel cacheModel)
314{
315    toImpl(contextRef)->setCacheModel(toCacheModel(cacheModel));
316}
317
318WKCacheModel WKContextGetCacheModel(WKContextRef contextRef)
319{
320    return toAPI(toImpl(contextRef)->cacheModel());
321}
322
323void WKContextSetProcessModel(WKContextRef contextRef, WKProcessModel processModel)
324{
325    toImpl(contextRef)->setProcessModel(toProcessModel(processModel));
326}
327
328WKProcessModel WKContextGetProcessModel(WKContextRef contextRef)
329{
330    return toAPI(toImpl(contextRef)->processModel());
331}
332
333void WKContextSetMaximumNumberOfProcesses(WKContextRef contextRef, unsigned numberOfProcesses)
334{
335    toImpl(contextRef)->setMaximumNumberOfProcesses(numberOfProcesses);
336}
337
338unsigned WKContextGetMaximumNumberOfProcesses(WKContextRef contextRef)
339{
340    return toImpl(contextRef)->maximumNumberOfProcesses();
341}
342
343void WKContextSetAlwaysUsesComplexTextCodePath(WKContextRef contextRef, bool alwaysUseComplexTextCodePath)
344{
345    toImpl(contextRef)->setAlwaysUsesComplexTextCodePath(alwaysUseComplexTextCodePath);
346}
347
348void WKContextSetShouldUseFontSmoothing(WKContextRef contextRef, bool useFontSmoothing)
349{
350    toImpl(contextRef)->setShouldUseFontSmoothing(useFontSmoothing);
351}
352
353void WKContextSetAdditionalPluginsDirectory(WKContextRef contextRef, WKStringRef pluginsDirectory)
354{
355#if ENABLE(NETSCAPE_PLUGIN_API)
356    toImpl(contextRef)->setAdditionalPluginsDirectory(toImpl(pluginsDirectory)->string());
357#else
358    UNUSED_PARAM(contextRef);
359    UNUSED_PARAM(pluginsDirectory);
360#endif
361}
362
363void WKContextRegisterURLSchemeAsEmptyDocument(WKContextRef contextRef, WKStringRef urlScheme)
364{
365    toImpl(contextRef)->registerURLSchemeAsEmptyDocument(toImpl(urlScheme)->string());
366}
367
368void WKContextRegisterURLSchemeAsSecure(WKContextRef contextRef, WKStringRef urlScheme)
369{
370    toImpl(contextRef)->registerURLSchemeAsSecure(toImpl(urlScheme)->string());
371}
372
373void WKContextRegisterURLSchemeAsCachePartitioned(WKContextRef contextRef, WKStringRef urlScheme)
374{
375#if ENABLE(CACHE_PARTITIONING)
376    toImpl(contextRef)->registerURLSchemeAsCachePartitioned(toImpl(urlScheme)->string());
377#else
378    UNUSED_PARAM(contextRef);
379    UNUSED_PARAM(urlScheme);
380#endif
381}
382
383void WKContextSetDomainRelaxationForbiddenForURLScheme(WKContextRef contextRef, WKStringRef urlScheme)
384{
385    toImpl(contextRef)->setDomainRelaxationForbiddenForURLScheme(toImpl(urlScheme)->string());
386}
387
388WKCookieManagerRef WKContextGetCookieManager(WKContextRef contextRef)
389{
390    return toAPI(toImpl(contextRef)->supplement<WebCookieManagerProxy>());
391}
392
393WKApplicationCacheManagerRef WKContextGetApplicationCacheManager(WKContextRef contextRef)
394{
395    return toAPI(toImpl(contextRef)->supplement<WebApplicationCacheManagerProxy>());
396}
397
398WKBatteryManagerRef WKContextGetBatteryManager(WKContextRef contextRef)
399{
400#if ENABLE(BATTERY_STATUS)
401    return toAPI(toImpl(contextRef)->supplement<WebBatteryManagerProxy>());
402#else
403    UNUSED_PARAM(contextRef);
404    return 0;
405#endif
406}
407
408WKDatabaseManagerRef WKContextGetDatabaseManager(WKContextRef contextRef)
409{
410#if ENABLE(SQL_DATABASE)
411    return toAPI(toImpl(contextRef)->supplement<WebDatabaseManagerProxy>());
412#else
413    UNUSED_PARAM(contextRef);
414    return 0;
415#endif
416}
417
418WKGeolocationManagerRef WKContextGetGeolocationManager(WKContextRef contextRef)
419{
420    return toAPI(toImpl(contextRef)->supplement<WebGeolocationManagerProxy>());
421}
422
423WKIconDatabaseRef WKContextGetIconDatabase(WKContextRef contextRef)
424{
425    return toAPI(toImpl(contextRef)->iconDatabase());
426}
427
428WKKeyValueStorageManagerRef WKContextGetKeyValueStorageManager(WKContextRef contextRef)
429{
430    return toAPI(toImpl(contextRef)->supplement<WebKeyValueStorageManager>());
431}
432
433WKMediaCacheManagerRef WKContextGetMediaCacheManager(WKContextRef contextRef)
434{
435    return toAPI(toImpl(contextRef)->supplement<WebMediaCacheManagerProxy>());
436}
437
438WKNotificationManagerRef WKContextGetNotificationManager(WKContextRef contextRef)
439{
440    return toAPI(toImpl(contextRef)->supplement<WebNotificationManagerProxy>());
441}
442
443WKPluginSiteDataManagerRef WKContextGetPluginSiteDataManager(WKContextRef contextRef)
444{
445#if ENABLE(NETSCAPE_PLUGIN_API)
446    return toAPI(toImpl(contextRef)->pluginSiteDataManager());
447#else
448    UNUSED_PARAM(contextRef);
449    return 0;
450#endif
451}
452
453WKResourceCacheManagerRef WKContextGetResourceCacheManager(WKContextRef contextRef)
454{
455    return toAPI(toImpl(contextRef)->supplement<WebResourceCacheManagerProxy>());
456}
457
458WKOriginDataManagerRef WKContextGetOriginDataManager(WKContextRef contextRef)
459{
460    return toAPI(toImpl(contextRef)->supplement<WebOriginDataManagerProxy>());
461}
462
463void WKContextStartMemorySampler(WKContextRef contextRef, WKDoubleRef interval)
464{
465    toImpl(contextRef)->startMemorySampler(toImpl(interval)->value());
466}
467
468void WKContextStopMemorySampler(WKContextRef contextRef)
469{
470    toImpl(contextRef)->stopMemorySampler();
471}
472
473void WKContextSetIconDatabasePath(WKContextRef contextRef, WKStringRef iconDatabasePath)
474{
475    toImpl(contextRef)->setIconDatabasePath(toImpl(iconDatabasePath)->string());
476}
477
478void WKContextAllowSpecificHTTPSCertificateForHost(WKContextRef contextRef, WKCertificateInfoRef certificateRef, WKStringRef hostRef)
479{
480    toImpl(contextRef)->allowSpecificHTTPSCertificateForHost(toImpl(certificateRef), toImpl(hostRef)->string());
481}
482
483WK_EXPORT void WKContextSetApplicationCacheDirectory(WKContextRef contextRef, WKStringRef applicationCacheDirectory)
484{
485    toImpl(contextRef)->setApplicationCacheDirectory(toImpl(applicationCacheDirectory)->string());
486}
487
488WK_EXPORT void WKContextSetDiskCacheDirectory(WKContextRef contextRef, WKStringRef diskCacheDirectory)
489{
490    toImpl(contextRef)->setDiskCacheDirectory(toImpl(diskCacheDirectory)->string());
491}
492
493WK_EXPORT void WKContextSetCookieStorageDirectory(WKContextRef contextRef, WKStringRef cookieStorageDirectory)
494{
495    toImpl(contextRef)->setCookieStorageDirectory(toImpl(cookieStorageDirectory)->string());
496}
497
498void WKContextDisableProcessTermination(WKContextRef contextRef)
499{
500    toImpl(contextRef)->disableProcessTermination();
501}
502
503void WKContextEnableProcessTermination(WKContextRef contextRef)
504{
505    toImpl(contextRef)->enableProcessTermination();
506}
507
508void WKContextSetHTTPPipeliningEnabled(WKContextRef contextRef, bool enabled)
509{
510    toImpl(contextRef)->setHTTPPipeliningEnabled(enabled);
511}
512
513void WKContextWarmInitialProcess(WKContextRef contextRef)
514{
515    toImpl(contextRef)->warmInitialProcess();
516}
517
518void WKContextGetStatistics(WKContextRef contextRef, void* context, WKContextGetStatisticsFunction callback)
519{
520    toImpl(contextRef)->getStatistics(0xFFFFFFFF, toGenericCallbackFunction(context, callback));
521}
522
523void WKContextGetStatisticsWithOptions(WKContextRef contextRef, WKStatisticsOptions optionsMask, void* context, WKContextGetStatisticsFunction callback)
524{
525    toImpl(contextRef)->getStatistics(optionsMask, toGenericCallbackFunction(context, callback));
526}
527
528void WKContextGarbageCollectJavaScriptObjects(WKContextRef contextRef)
529{
530    toImpl(contextRef)->garbageCollectJavaScriptObjects();
531}
532
533void WKContextSetJavaScriptGarbageCollectorTimerEnabled(WKContextRef contextRef, bool enable)
534{
535    toImpl(contextRef)->setJavaScriptGarbageCollectorTimerEnabled(enable);
536}
537
538void WKContextSetUsesNetworkProcess(WKContextRef contextRef, bool usesNetworkProcess)
539{
540    toImpl(contextRef)->setUsesNetworkProcess(usesNetworkProcess);
541}
542
543void WKContextUseTestingNetworkSession(WKContextRef context)
544{
545    toImpl(context)->useTestingNetworkSession();
546}
547
548WKDictionaryRef WKContextCopyPlugInAutoStartOriginHashes(WKContextRef contextRef)
549{
550    return toAPI(toImpl(contextRef)->plugInAutoStartOriginHashes().leakRef());
551}
552
553void WKContextSetPlugInAutoStartOriginHashes(WKContextRef contextRef, WKDictionaryRef dictionaryRef)
554{
555    if (!dictionaryRef)
556        return;
557    toImpl(contextRef)->setPlugInAutoStartOriginHashes(*toImpl(dictionaryRef));
558}
559
560void WKContextSetPlugInAutoStartOriginsFilteringOutEntriesAddedAfterTime(WKContextRef contextRef, WKDictionaryRef dictionaryRef, double time)
561{
562    if (!dictionaryRef)
563        return;
564    toImpl(contextRef)->setPlugInAutoStartOriginsFilteringOutEntriesAddedAfterTime(*toImpl(dictionaryRef), time);
565}
566
567void WKContextSetPlugInAutoStartOrigins(WKContextRef contextRef, WKArrayRef arrayRef)
568{
569    if (!arrayRef)
570        return;
571    toImpl(contextRef)->setPlugInAutoStartOrigins(*toImpl(arrayRef));
572}
573
574void WKContextSetInvalidMessageFunction(WKContextInvalidMessageFunction invalidMessageFunction)
575{
576    WebContext::setInvalidMessageCallback(invalidMessageFunction);
577}
578
579void WKContextSetMemoryCacheDisabled(WKContextRef contextRef, bool disabled)
580{
581    toImpl(contextRef)->setMemoryCacheDisabled(disabled);
582}
583