770f210bc9490da11dc242d2d08895150973d711
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / efl / ewk_context.cpp
1 /*
2  * Copyright (C) 2012 Samsung Electronics
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this program; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #include "config.h"
22 #include "ewk_context.h"
23
24 #include "BatteryProvider.h"
25 #include "ContextHistoryClientEfl.h"
26 #include "DownloadManagerEfl.h"
27 #include "RequestManagerClientEfl.h"
28 #include "WKAPICast.h"
29 #include "WKContextPrivate.h"
30 #include "WKContextSoup.h"
31 #include "WKNumber.h"
32 #include "WKString.h"
33 #include "WebContext.h"
34 #include "WebIconDatabase.h"
35 #include "ewk_application_cache_manager_private.h"
36 #include "ewk_context_private.h"
37 #include "ewk_cookie_manager_private.h"
38 #include "ewk_database_manager_private.h"
39 #include "ewk_favicon_database_private.h"
40 #include "ewk_storage_manager_private.h"
41 #include "ewk_url_scheme_request_private.h"
42 #include <JavaScriptCore/JSContextRef.h>
43 #include <WebCore/FileSystem.h>
44 #include <WebCore/IconDatabase.h>
45 #include <WebCore/Language.h>
46 #include <wtf/HashMap.h>
47 #include <wtf/NeverDestroyed.h>
48 #include <wtf/text/WTFString.h>
49
50 #if ENABLE(SPELLCHECK)
51 #include "TextCheckerClientEfl.h"
52 #endif
53
54 using namespace WebCore;
55 using namespace WebKit;
56
57 typedef HashMap<WKContextRef, EwkContext*> ContextMap;
58
59 static inline ContextMap& contextMap()
60 {
61     static NeverDestroyed<ContextMap> map;
62     return map;
63 }
64
65 EwkContext::EwkContext(WKContextRef context, const String& extensionsPath)
66     : m_context(context)
67     , m_databaseManager(std::make_unique<EwkDatabaseManager>(WKContextGetDatabaseManager(context)))
68     , m_storageManager(std::make_unique<EwkStorageManager>(WKContextGetKeyValueStorageManager(context)))
69 #if ENABLE(BATTERY_STATUS)
70     , m_batteryProvider(BatteryProvider::create(context))
71 #endif
72     , m_downloadManager(std::make_unique<DownloadManagerEfl>(context))
73     , m_requestManagerClient(std::make_unique<RequestManagerClientEfl>(context))
74     , m_historyClient(std::make_unique<ContextHistoryClientEfl>(context))
75     , m_jsGlobalContext(nullptr)
76     , m_extensionsPath(extensionsPath)
77 {
78     ContextMap::AddResult result = contextMap().add(context, this);
79     ASSERT_UNUSED(result, result.isNewEntry);
80
81 #if ENABLE(MEMORY_SAMPLER)
82     static bool initializeMemorySampler = false;
83     static const char environmentVariable[] = "SAMPLE_MEMORY";
84
85     if (!initializeMemorySampler && getenv(environmentVariable)) {
86         WKContextStartMemorySampler(context, adoptWK(WKDoubleCreate(0.0)).get());
87         initializeMemorySampler = true;
88     }
89 #endif
90
91 #if ENABLE(SPELLCHECK)
92     // Load the default dictionary to show context menu spellchecking items
93     // independently of checking spelling while typing setting.
94     TextCheckerClientEfl::instance().ensureSpellCheckingLanguage();
95 #endif
96
97     m_callbackForMessageFromInjectedBundle.callback = nullptr;
98     m_callbackForMessageFromInjectedBundle.userData = nullptr;
99
100     if (!extensionsPath.isEmpty()) {
101         WKContextInjectedBundleClientV1 client;
102         memset(&client, 0, sizeof(client));
103
104         client.base.version = 1;
105         client.base.clientInfo = this;
106         client.didReceiveMessageFromInjectedBundle = didReceiveMessageFromInjectedBundle;
107         client.didReceiveSynchronousMessageFromInjectedBundle = didReceiveSynchronousMessageFromInjectedBundle;
108         client.getInjectedBundleInitializationUserData = getInjectedBundleInitializationUserData;
109
110         WKContextSetInjectedBundleClient(m_context.get(), &client.base);
111     }
112 }
113
114 EwkContext::~EwkContext()
115 {
116     ASSERT(contextMap().get(m_context.get()) == this);
117
118     if (m_jsGlobalContext)
119         JSGlobalContextRelease(m_jsGlobalContext);
120
121     contextMap().remove(m_context.get());
122 }
123
124 PassRefPtr<EwkContext> EwkContext::findOrCreateWrapper(WKContextRef context)
125 {
126     if (contextMap().contains(context))
127         return contextMap().get(context);
128
129     return adoptRef(new EwkContext(context));
130 }
131
132 PassRefPtr<EwkContext> EwkContext::create()
133 {
134     return adoptRef(new EwkContext(adoptWK(WKContextCreate()).get()));
135 }
136
137 static String bundlePathForExtension()
138 {
139     String bundlePathForExtension = WebCore::pathByAppendingComponent(String::fromUTF8(TEST_LIB_DIR), EXTENSIONMANAGERNAME);
140     if (WebCore::fileExists(bundlePathForExtension))
141         return bundlePathForExtension;
142
143     bundlePathForExtension = WebCore::pathByAppendingComponent(String::fromUTF8(EXTENSIONMANAGERDIR), EXTENSIONMANAGERNAME);
144     if (WebCore::fileExists(bundlePathForExtension))
145         return bundlePathForExtension;
146
147     return emptyString();
148 }
149
150 PassRefPtr<EwkContext> EwkContext::create(const String& extensionsPath)
151 {   
152     String bundlePath = bundlePathForExtension();
153     if (bundlePath.isEmpty())
154         return 0;
155
156     WKRetainPtr<WKStringRef> path = adoptWK(toCopiedAPI(bundlePath));
157
158     return adoptRef(new EwkContext(adoptWK(WKContextCreateWithInjectedBundlePath(path.get())).get(), extensionsPath));
159 }
160
161 EwkContext* EwkContext::defaultContext()
162 {
163     static EwkContext* defaultInstance = create().leakRef();
164
165     return defaultInstance;
166 }
167
168 EwkApplicationCacheManager* EwkContext::applicationCacheManager()
169 {
170     if (!m_applicationCacheManager)
171         m_applicationCacheManager = std::make_unique<EwkApplicationCacheManager>(WKContextGetApplicationCacheManager(m_context.get()));
172
173     return m_applicationCacheManager.get();
174 }
175
176 EwkCookieManager* EwkContext::cookieManager()
177 {
178     if (!m_cookieManager)
179         m_cookieManager = std::make_unique<EwkCookieManager>(WKContextGetCookieManager(m_context.get()));
180
181     return m_cookieManager.get();
182 }
183
184 EwkDatabaseManager* EwkContext::databaseManager()
185 {
186     return m_databaseManager.get();
187 }
188
189 void EwkContext::ensureFaviconDatabase()
190 {
191     if (m_faviconDatabase)
192         return;
193
194     m_faviconDatabase = std::make_unique<EwkFaviconDatabase>(WKContextGetIconDatabase(m_context.get()));
195 }
196
197 bool EwkContext::setFaviconDatabaseDirectoryPath(const String& databaseDirectory)
198 {
199     ensureFaviconDatabase();
200     // FIXME: Hole in WK2 API layering must be fixed when C API is available.
201     WebIconDatabase* iconDatabase = toImpl(WKContextGetIconDatabase(m_context.get()));
202
203     // The database path is already open so its path was
204     // already set.
205     if (iconDatabase->isOpen())
206         return false;
207
208     // If databaseDirectory is empty, we use the default database path for the platform.
209     String databasePath = databaseDirectory.isEmpty() ? toImpl(m_context.get())->iconDatabasePath() : pathByAppendingComponent(databaseDirectory, WebCore::IconDatabase::defaultDatabaseFilename());
210     toImpl(m_context.get())->setIconDatabasePath(databasePath);
211
212     return true;
213 }
214
215 EwkFaviconDatabase* EwkContext::faviconDatabase()
216 {
217     ensureFaviconDatabase();
218     ASSERT(m_faviconDatabase);
219
220     return m_faviconDatabase.get();
221 }
222
223 EwkStorageManager* EwkContext::storageManager() const
224 {
225     return m_storageManager.get();
226 }
227
228 RequestManagerClientEfl* EwkContext::requestManager()
229 {
230     return m_requestManagerClient.get();
231 }
232
233 void EwkContext::addVisitedLink(const String& visitedURL)
234 {
235     WKContextAddVisitedLink(m_context.get(), adoptWK(toCopiedAPI(visitedURL)).get());
236 }
237
238 // Ewk_Cache_Model enum validation
239 inline WKCacheModel toWKCacheModel(Ewk_Cache_Model cacheModel)
240 {
241     switch (cacheModel) {
242     case EWK_CACHE_MODEL_DOCUMENT_VIEWER:
243         return kWKCacheModelDocumentViewer;
244     case EWK_CACHE_MODEL_DOCUMENT_BROWSER:
245         return kWKCacheModelDocumentBrowser;
246     case EWK_CACHE_MODEL_PRIMARY_WEBBROWSER:
247         return kWKCacheModelPrimaryWebBrowser;
248     }
249     ASSERT_NOT_REACHED();
250
251     return kWKCacheModelDocumentViewer;
252 }
253
254 void EwkContext::setCacheModel(Ewk_Cache_Model cacheModel)
255 {
256     WKContextSetCacheModel(m_context.get(), toWKCacheModel(cacheModel));
257 }
258
259 Ewk_Cache_Model EwkContext::cacheModel() const
260 {
261     return static_cast<Ewk_Cache_Model>(WKContextGetCacheModel(m_context.get()));
262 }
263
264 inline WKProcessModel toWKProcessModel(Ewk_Process_Model processModel)
265 {
266     switch (processModel) {
267     case EWK_PROCESS_MODEL_SHARED_SECONDARY:
268         return kWKProcessModelSharedSecondaryProcess;
269     case EWK_PROCESS_MODEL_MULTIPLE_SECONDARY:
270         return kWKProcessModelMultipleSecondaryProcesses;
271     }
272     ASSERT_NOT_REACHED();
273
274     return kWKProcessModelSharedSecondaryProcess;
275 }
276
277 void EwkContext::setProcessModel(Ewk_Process_Model processModel)
278 {
279     WKProcessModel newWKProcessModel = toWKProcessModel(processModel);
280
281     if (WKContextGetProcessModel(m_context.get()) == newWKProcessModel)
282         return;
283
284     WKContextSetUsesNetworkProcess(m_context.get(), newWKProcessModel == kWKProcessModelMultipleSecondaryProcesses);
285     WKContextSetProcessModel(m_context.get(), newWKProcessModel);
286 }
287
288 inline Ewk_Process_Model toEwkProcessModel(WKProcessModel processModel)
289 {
290     switch (processModel) {
291     case kWKProcessModelSharedSecondaryProcess:
292         return EWK_PROCESS_MODEL_SHARED_SECONDARY;
293     case kWKProcessModelMultipleSecondaryProcesses:
294         return EWK_PROCESS_MODEL_MULTIPLE_SECONDARY;
295     }
296     ASSERT_NOT_REACHED();
297
298     return EWK_PROCESS_MODEL_SHARED_SECONDARY;
299 }
300
301 Ewk_Process_Model EwkContext::processModel() const
302 {
303     return toEwkProcessModel(WKContextGetProcessModel(m_context.get()));
304 }
305
306 #if ENABLE(NETSCAPE_PLUGIN_API)
307 void EwkContext::setAdditionalPluginPath(const String& path)
308 {
309     // FIXME: Hole in WK2 API layering must be fixed when C API is available.
310     toImpl(m_context.get())->setAdditionalPluginsDirectory(path);
311 }
312 #endif
313
314 void EwkContext::clearResourceCache()
315 {
316     WKResourceCacheManagerClearCacheForAllOrigins(WKContextGetResourceCacheManager(m_context.get()), WKResourceCachesToClearAll);
317 }
318
319
320 JSGlobalContextRef EwkContext::jsGlobalContext()
321 {
322     if (!m_jsGlobalContext)
323         m_jsGlobalContext = JSGlobalContextCreate(0);
324
325     return m_jsGlobalContext;
326 }
327
328 Ewk_Application_Cache_Manager* ewk_context_application_cache_manager_get(const Ewk_Context* ewkContext)
329 {
330     EWK_OBJ_GET_IMPL_OR_RETURN(const EwkContext, ewkContext, impl, nullptr);
331
332     return const_cast<EwkContext*>(impl)->applicationCacheManager();
333 }
334
335 Ewk_Cookie_Manager* ewk_context_cookie_manager_get(const Ewk_Context* ewkContext)
336 {
337     EWK_OBJ_GET_IMPL_OR_RETURN(const EwkContext, ewkContext, impl, nullptr);
338
339     return const_cast<EwkContext*>(impl)->cookieManager();
340 }
341
342 Ewk_Database_Manager* ewk_context_database_manager_get(const Ewk_Context* ewkContext)
343 {
344     EWK_OBJ_GET_IMPL_OR_RETURN(const EwkContext, ewkContext, impl, nullptr);
345
346     return const_cast<EwkContext*>(impl)->databaseManager();
347 }
348
349 Eina_Bool ewk_context_favicon_database_directory_set(Ewk_Context* ewkContext, const char* directoryPath)
350 {
351     EWK_OBJ_GET_IMPL_OR_RETURN(EwkContext, ewkContext, impl, false);
352
353     return impl->setFaviconDatabaseDirectoryPath(String::fromUTF8(directoryPath));
354 }
355
356 Ewk_Favicon_Database* ewk_context_favicon_database_get(const Ewk_Context* ewkContext)
357 {
358     EWK_OBJ_GET_IMPL_OR_RETURN(const EwkContext, ewkContext, impl, nullptr);
359
360     return const_cast<EwkContext*>(impl)->faviconDatabase();
361 }
362
363 Ewk_Storage_Manager* ewk_context_storage_manager_get(const Ewk_Context* ewkContext)
364 {
365     EWK_OBJ_GET_IMPL_OR_RETURN(const EwkContext, ewkContext, impl, nullptr);
366
367     return impl->storageManager();
368 }
369
370 DownloadManagerEfl* EwkContext::downloadManager() const
371 {
372     return m_downloadManager.get();
373 }
374
375 ContextHistoryClientEfl* EwkContext::historyClient()
376 {
377     return m_historyClient.get();
378 }
379
380 static inline EwkContext* toEwkContext(const void* clientInfo)
381 {
382     return static_cast<EwkContext*>(const_cast<void*>(clientInfo));
383 }
384
385 void EwkContext::didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
386 {
387     toEwkContext(clientInfo)->processReceivedMessageFromInjectedBundle(messageName, messageBody, nullptr);
388 }
389
390 void EwkContext::didReceiveSynchronousMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnData, const void* clientInfo)
391 {
392     toEwkContext(clientInfo)->processReceivedMessageFromInjectedBundle(messageName, messageBody, returnData);
393 }
394
395 WKTypeRef EwkContext::getInjectedBundleInitializationUserData(WKContextRef, const void* clientInfo)
396 {
397     return static_cast<WKTypeRef>(toCopiedAPI(toEwkContext(clientInfo)->extensionsPath()));
398 }
399
400 void EwkContext::setMessageFromInjectedBundleCallback(Ewk_Context_Message_From_Injected_Bundle_Cb callback, void* userData)
401 {
402     m_callbackForMessageFromInjectedBundle.userData = userData;
403
404     if (m_callbackForMessageFromInjectedBundle.callback == callback)
405         return;
406
407     m_callbackForMessageFromInjectedBundle.callback = callback;
408 }
409
410 void EwkContext::processReceivedMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody, WKTypeRef* returnData)
411 {
412     if (!m_callbackForMessageFromInjectedBundle.callback)
413         return;
414
415     CString name = toImpl(messageName)->string().utf8();
416     CString body;
417     if (messageBody && WKStringGetTypeID() == WKGetTypeID(messageBody))
418         body = toImpl(static_cast<WKStringRef>(messageBody))->string().utf8();
419
420     if (returnData) {
421         char* returnString = nullptr;
422         m_callbackForMessageFromInjectedBundle.callback(name.data(), body.data(), &returnString, m_callbackForMessageFromInjectedBundle.userData);
423         if (returnString) {
424             *returnData = WKStringCreateWithUTF8CString(returnString);
425             free(returnString);
426         } else
427             *returnData = WKStringCreateWithUTF8CString("");
428     } else
429         m_callbackForMessageFromInjectedBundle.callback(name.data(), body.data(), nullptr, m_callbackForMessageFromInjectedBundle.userData);
430 }
431
432 Ewk_TLS_Error_Policy EwkContext::ignoreTLSErrors() const
433 {
434     return toImpl(m_context.get())->ignoreTLSErrors() ? EWK_TLS_ERROR_POLICY_IGNORE : EWK_TLS_ERROR_POLICY_FAIL;
435 }
436
437 void EwkContext::setIgnoreTLSErrors(Ewk_TLS_Error_Policy TLSErrorPolicy) const
438 {
439     bool isNewPolicy = TLSErrorPolicy == EWK_TLS_ERROR_POLICY_IGNORE;
440     if (toImpl(m_context.get())->ignoreTLSErrors() == isNewPolicy)
441         return;
442
443     toImpl(m_context.get())->setIgnoreTLSErrors(isNewPolicy);
444 }
445
446 Ewk_Context* ewk_context_default_get()
447 {
448     return EwkContext::defaultContext();
449 }
450
451 Ewk_Context* ewk_context_new()
452 {
453     return EwkContext::create().leakRef();
454 }
455
456 Ewk_Context* ewk_context_new_with_extensions_path(const char* path)
457 {
458     EINA_SAFETY_ON_NULL_RETURN_VAL(path, nullptr);
459
460     return EwkContext::create(String::fromUTF8(path)).leakRef();
461 }
462
463 Eina_Bool ewk_context_url_scheme_register(Ewk_Context* ewkContext, const char* scheme, Ewk_Url_Scheme_Request_Cb callback, void* userData)
464 {
465     EWK_OBJ_GET_IMPL_OR_RETURN(EwkContext, ewkContext, impl, false);
466     EINA_SAFETY_ON_NULL_RETURN_VAL(scheme, false);
467     EINA_SAFETY_ON_NULL_RETURN_VAL(callback, false);
468
469     impl->requestManager()->registerURLSchemeHandler(String::fromUTF8(scheme), callback, userData);
470
471     return true;
472 }
473
474 void ewk_context_history_callbacks_set(Ewk_Context* ewkContext, Ewk_History_Navigation_Cb navigate, Ewk_History_Client_Redirection_Cb clientRedirect, Ewk_History_Server_Redirection_Cb serverRedirect, Ewk_History_Title_Update_Cb titleUpdate, Ewk_History_Populate_Visited_Links_Cb populateVisitedLinks, void* data)
475 {
476     EWK_OBJ_GET_IMPL_OR_RETURN(EwkContext, ewkContext, impl);
477
478     impl->historyClient()->setCallbacks(navigate, clientRedirect, serverRedirect, titleUpdate, populateVisitedLinks, data);
479 }
480
481 void ewk_context_visited_link_add(Ewk_Context* ewkContext, const char* visitedURL)
482 {
483     EWK_OBJ_GET_IMPL_OR_RETURN(EwkContext, ewkContext, impl);
484     EINA_SAFETY_ON_NULL_RETURN(visitedURL);
485
486     impl->addVisitedLink(visitedURL);
487 }
488
489 Eina_Bool ewk_context_cache_model_set(Ewk_Context* ewkContext, Ewk_Cache_Model cacheModel)
490 {
491     EWK_OBJ_GET_IMPL_OR_RETURN(EwkContext, ewkContext, impl, false);
492
493     impl->setCacheModel(cacheModel);
494
495     return true;
496 }
497
498 Ewk_Cache_Model ewk_context_cache_model_get(const Ewk_Context* ewkContext)
499 {
500     EWK_OBJ_GET_IMPL_OR_RETURN(const EwkContext, ewkContext, impl, EWK_CACHE_MODEL_DOCUMENT_VIEWER);
501
502     return impl->cacheModel();
503 }
504
505 Eina_Bool ewk_context_additional_plugin_path_set(Ewk_Context* ewkContext, const char* path)
506 {
507 #if ENABLE(NETSCAPE_PLUGIN_API)
508     EWK_OBJ_GET_IMPL_OR_RETURN(EwkContext, ewkContext, impl, false);
509     EINA_SAFETY_ON_NULL_RETURN_VAL(path, false);
510
511     impl->setAdditionalPluginPath(String::fromUTF8(path));
512     return true;
513 #else
514     UNUSED_PARAM(ewkContext);
515     UNUSED_PARAM(path);
516     return false;
517 #endif
518 }
519
520 void ewk_context_resource_cache_clear(Ewk_Context* ewkContext)
521 {
522     EWK_OBJ_GET_IMPL_OR_RETURN(EwkContext, ewkContext, impl);
523
524     impl->clearResourceCache();
525 }
526
527 void ewk_context_message_post_to_injected_bundle(Ewk_Context* ewkContext, const char* name, const char* body)
528 {
529     EWK_OBJ_GET_IMPL_OR_RETURN(EwkContext, ewkContext, impl);
530     EINA_SAFETY_ON_NULL_RETURN(name);
531     EINA_SAFETY_ON_NULL_RETURN(body);
532
533     WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString(name));
534     WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithUTF8CString(body));
535     WKContextPostMessageToInjectedBundle(impl->wkContext(), messageName.get(), messageBody.get());
536 }
537
538 void ewk_context_message_from_injected_bundle_callback_set(Ewk_Context* ewkContext, Ewk_Context_Message_From_Injected_Bundle_Cb callback, void* userData)
539 {
540     EWK_OBJ_GET_IMPL_OR_RETURN(EwkContext, ewkContext, impl);
541
542     impl->setMessageFromInjectedBundleCallback(callback, userData);
543 }
544
545 Eina_Bool ewk_context_process_model_set(Ewk_Context* ewkContext, Ewk_Process_Model processModel)
546 {
547 #if ENABLE(NETWORK_PROCESS)
548     EWK_OBJ_GET_IMPL_OR_RETURN(EwkContext, ewkContext, impl, false);
549
550     impl->setProcessModel(processModel);
551
552     return true;
553 #else
554     UNUSED_PARAM(ewkContext);
555     UNUSED_PARAM(processModel);
556     return false;
557 #endif
558 }
559
560 Ewk_Process_Model ewk_context_process_model_get(const Ewk_Context* ewkContext)
561 {
562 #if ENABLE(NETWORK_PROCESS)
563     EWK_OBJ_GET_IMPL_OR_RETURN(const EwkContext, ewkContext, impl, EWK_PROCESS_MODEL_SHARED_SECONDARY);
564
565     return impl->processModel();
566 #else
567     UNUSED_PARAM(ewkContext);
568     return EWK_PROCESS_MODEL_SHARED_SECONDARY;
569 #endif
570 }
571
572 Ewk_TLS_Error_Policy ewk_context_tls_error_policy_get(const Ewk_Context* context)
573 {
574     EWK_OBJ_GET_IMPL_OR_RETURN(const EwkContext, context, impl, EWK_TLS_ERROR_POLICY_FAIL);
575
576     return impl->ignoreTLSErrors();
577 }
578
579 void ewk_context_tls_error_policy_set(Ewk_Context* context, Ewk_TLS_Error_Policy tls_error_policy)
580 {
581     EWK_OBJ_GET_IMPL_OR_RETURN(const EwkContext, context, impl);
582     impl->setIgnoreTLSErrors(tls_error_policy);
583 }
584
585 void ewk_context_preferred_languages_set(Eina_List* languages)
586 {
587     Vector<String> preferredLanguages;
588     if (languages) {
589         Eina_List* l;
590         void* data;
591         EINA_LIST_FOREACH(languages, l, data)
592             preferredLanguages.append(String::fromUTF8(static_cast<char*>(data)).lower().replace("_", "-"));
593     }
594
595     WebCore::overrideUserPreferredLanguages(preferredLanguages);
596     WebCore::languageDidChange();
597 }