diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-07-30 11:37:48 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-07-30 11:38:52 +0200 |
commit | 89e2486a48b739f8d771d69ede5a6a1b244a10fc (patch) | |
tree | 503b1a7812cf97d93704c32437eb5f62dc1a1ff9 /Source/WebKit2/UIProcess/API | |
parent | 625f028249cb37c55bbbd153f3902afd0b0756d9 (diff) | |
download | qtwebkit-89e2486a48b739f8d771d69ede5a6a1b244a10fc.tar.gz |
Imported WebKit commit 0282df8ca7c11d8c8a66ea18543695c69f545a27 (http://svn.webkit.org/repository/webkit/trunk@124002)
New snapshot with prospective Mountain Lion build fix
Diffstat (limited to 'Source/WebKit2/UIProcess/API')
57 files changed, 3163 insertions, 73 deletions
diff --git a/Source/WebKit2/UIProcess/API/C/WKContext.cpp b/Source/WebKit2/UIProcess/API/C/WKContext.cpp index 7fadf3087..e90d1129a 100644 --- a/Source/WebKit2/UIProcess/API/C/WKContext.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKContext.cpp @@ -112,7 +112,7 @@ void WKContextGetGlobalStatistics(WKContextStatistics* statistics) statistics->wkViewCount = webContextStatistics.wkViewCount; statistics->wkPageCount = webContextStatistics.wkPageCount; - statistics->wkFrameCount = webContextStatistics.wkViewCount; + statistics->wkFrameCount = webContextStatistics.wkFrameCount; } void WKContextAddVisitedLink(WKContextRef contextRef, WKStringRef visitedURL) diff --git a/Source/WebKit2/UIProcess/API/C/WKIntentData.cpp b/Source/WebKit2/UIProcess/API/C/WKIntentData.cpp index a42f530ac..7a92db54c 100644 --- a/Source/WebKit2/UIProcess/API/C/WKIntentData.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKIntentData.cpp @@ -29,6 +29,8 @@ #include "ImmutableArray.h" #include "ImmutableDictionary.h" #include "WKAPICast.h" +#include "WKDictionary.h" +#include "WKString.h" #if ENABLE(WEB_INTENTS) #include "WebIntentData.h" @@ -45,6 +47,27 @@ WKTypeID WKIntentDataGetTypeID() #endif } +WKIntentDataRef WKIntentDataCreate(WKDictionaryRef initDictionaryRef) +{ +#if ENABLE(WEB_INTENTS) + IntentData intentData; + WKStringRef action = static_cast<WKStringRef>(WKDictionaryGetItemForKey(initDictionaryRef, WKStringCreateWithUTF8CString("action"))); + ASSERT(action); + intentData.action = toImpl(action)->string(); + WKStringRef type = static_cast<WKStringRef>(WKDictionaryGetItemForKey(initDictionaryRef, WKStringCreateWithUTF8CString("type"))); + ASSERT(type); + intentData.type = toImpl(type)->string(); + WKSerializedScriptValueRef data = static_cast<WKSerializedScriptValueRef>(WKDictionaryGetItemForKey(initDictionaryRef, WKStringCreateWithUTF8CString("data"))); + if (data) + intentData.data = toImpl(data)->dataReference().vector(); + + RefPtr<WebIntentData> webIntentData = WebIntentData::create(intentData); + return toAPI(webIntentData.release().leakRef()); +#else + return 0; +#endif +} + WKStringRef WKIntentDataCopyAction(WKIntentDataRef intentRef) { #if ENABLE(WEB_INTENTS) diff --git a/Source/WebKit2/UIProcess/API/C/WKIntentData.h b/Source/WebKit2/UIProcess/API/C/WKIntentData.h index 030555b4b..1f809ec8d 100644 --- a/Source/WebKit2/UIProcess/API/C/WKIntentData.h +++ b/Source/WebKit2/UIProcess/API/C/WKIntentData.h @@ -33,6 +33,9 @@ extern "C" { #endif WK_EXPORT WKTypeID WKIntentDataGetTypeID(); + +WK_EXPORT WKIntentDataRef WKIntentDataCreate(WKDictionaryRef initDictionary); + WK_EXPORT WKStringRef WKIntentDataCopyAction(WKIntentDataRef intentRef); WK_EXPORT WKStringRef WKIntentDataCopyType(WKIntentDataRef intentRef); WK_EXPORT WKURLRef WKIntentDataCopyService(WKIntentDataRef intentRef); diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp b/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp index 727781f01..243a17369 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp @@ -823,3 +823,13 @@ void WKPreferencesResetTestRunnerOverrides(WKPreferencesRef preferencesRef) // are usually always the same (in the UI process), they are not sent to web process, not triggering the reset. toImpl(preferencesRef)->forceUpdate(); } + +void WKPreferencesSetDiagnosticLoggingEnabled(WKPreferencesRef preferencesRef, bool enabled) +{ + toImpl(preferencesRef)->setDiagnosticLoggingEnabled(enabled); +} + +bool WKPreferencesGetDiagnosticLoggingEnabled(WKPreferencesRef preferencesRef) +{ + return toImpl(preferencesRef)->diagnosticLoggingEnabled(); +} diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h b/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h index 6dbc47310..371c539a1 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h +++ b/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h @@ -187,6 +187,10 @@ WK_EXPORT bool WKPreferencesGetJavaEnabledForLocalFiles(WKPreferencesRef prefere WK_EXPORT void WKPreferencesSetRequestAnimationFrameEnabled(WKPreferencesRef, bool); WK_EXPORT bool WKPreferencesGetRequestAnimationFrameEnabled(WKPreferencesRef); +// Defaults to false +WK_EXPORT void WKPreferencesSetDiagnosticLoggingEnabled(WKPreferencesRef preferencesRef, bool enabled); +WK_EXPORT bool WKPreferencesGetDiagnosticLoggingEnabled(WKPreferencesRef preferencesRef); + WK_EXPORT void WKPreferencesResetTestRunnerOverrides(WKPreferencesRef preferencesRef); #ifdef __cplusplus diff --git a/Source/WebKit2/UIProcess/API/efl/EWebKit2.h b/Source/WebKit2/UIProcess/API/efl/EWebKit2.h index 597cf24cb..9a052da4b 100644 --- a/Source/WebKit2/UIProcess/API/efl/EWebKit2.h +++ b/Source/WebKit2/UIProcess/API/efl/EWebKit2.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Samsung Electronics + * Copyright (C) 2012 Intel Corporation. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -29,8 +30,11 @@ #include "ewk_context.h" #include "ewk_cookie_manager.h" +#include "ewk_download_job.h" +#include "ewk_form_submission_request.h" #include "ewk_intent.h" #include "ewk_intent_service.h" +#include "ewk_main.h" #include "ewk_navigation_policy_decision.h" #include "ewk_url_request.h" #include "ewk_url_response.h" diff --git a/Source/WebKit2/UIProcess/API/efl/NetworkInfoProvider.cpp b/Source/WebKit2/UIProcess/API/efl/NetworkInfoProvider.cpp new file mode 100644 index 000000000..54a6921da --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/NetworkInfoProvider.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "NetworkInfoProvider.h" + +#if ENABLE(NETWORK_INFO) + +#include "WKNetworkInfoManager.h" +#include <NotImplemented.h> + +static inline NetworkInfoProvider* toNetworkInfoProvider(const void* clientInfo) +{ + return static_cast<NetworkInfoProvider*>(const_cast<void*>(clientInfo)); +} + +static void startUpdatingCallback(WKNetworkInfoManagerRef, const void* clientInfo) +{ + toNetworkInfoProvider(clientInfo)->startUpdating(); +} + +static void stopUpdatingCallback(WKNetworkInfoManagerRef, const void* clientInfo) +{ + toNetworkInfoProvider(clientInfo)->stopUpdating(); +} + +static double getBandwidthCallback(WKNetworkInfoManagerRef, const void* clientInfo) +{ + return toNetworkInfoProvider(clientInfo)->bandwidth(); +} + +static bool isMeteredCallback(WKNetworkInfoManagerRef, const void* clientInfo) +{ + return toNetworkInfoProvider(clientInfo)->metered(); +} + +PassRefPtr<NetworkInfoProvider> NetworkInfoProvider::create(WKNetworkInfoManagerRef wkManager) +{ + return adoptRef(new NetworkInfoProvider(wkManager)); +} + +NetworkInfoProvider::NetworkInfoProvider(WKNetworkInfoManagerRef wkManager) + : m_wkNetworkInfoManager(wkManager) +{ + ASSERT(wkManager); + + WKNetworkInfoProvider wkNetworkInfoProvider = { + kWKNetworkInfoProviderCurrentVersion, + this, // clientInfo + startUpdatingCallback, + stopUpdatingCallback, + getBandwidthCallback, + isMeteredCallback + }; + WKNetworkInfoManagerSetProvider(m_wkNetworkInfoManager.get(), &wkNetworkInfoProvider); +} + +NetworkInfoProvider::~NetworkInfoProvider() +{ +} + +double NetworkInfoProvider::bandwidth() const +{ + return m_provider.bandwidth(); +} + +bool NetworkInfoProvider::metered() const +{ + notImplemented(); + + return false; +} + +void NetworkInfoProvider::startUpdating() +{ + m_provider.startUpdating(); +} + +void NetworkInfoProvider::stopUpdating() +{ + m_provider.stopUpdating(); +} + +#endif // ENABLE(NETWORK_INFO) diff --git a/Source/WebKit2/UIProcess/API/efl/NetworkInfoProvider.h b/Source/WebKit2/UIProcess/API/efl/NetworkInfoProvider.h new file mode 100644 index 000000000..b9f86e6e5 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/NetworkInfoProvider.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NetworkInfoProvider_h +#define NetworkInfoProvider_h + +#if ENABLE(NETWORK_INFO) + +#include <NetworkInfoClient.h> +#include <NetworkInfoProviderEfl.h> +#include <WebKit2/WKBase.h> +#include <WebKit2/WKRetainPtr.h> +#include <wtf/PassRefPtr.h> + +class NetworkInfoProvider : public RefCounted<NetworkInfoProvider>, public WebCore::NetworkInfoClient { +public: + virtual ~NetworkInfoProvider(); + static PassRefPtr<NetworkInfoProvider> create(WKNetworkInfoManagerRef); + + // NetworkInfoClient interface. + virtual double bandwidth() const; + virtual bool metered() const; + + virtual void startUpdating(); + virtual void stopUpdating(); + +private: + NetworkInfoProvider(WKNetworkInfoManagerRef); + + WKRetainPtr<WKNetworkInfoManagerRef> m_wkNetworkInfoManager; + WebCore::NetworkInfoProviderEfl m_provider; +}; + +#endif // ENABLE(NETWORK_INFO) + +#endif // NetworkInfoProvider_h diff --git a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp index e69f87d28..79d20a17d 100644 --- a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp +++ b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp @@ -32,6 +32,10 @@ #include "WebContext.h" #include "WebContextMenuProxy.h" #include "WebPageProxy.h" +#include "ewk_context.h" +#include "ewk_context_private.h" +#include "ewk_download_job.h" +#include "ewk_download_job_private.h" #include "ewk_view_private.h" using namespace WebCore; @@ -72,9 +76,7 @@ void PageClientImpl::scrollView(const WebCore::IntRect& scrollRect, const WebCor WebCore::IntSize PageClientImpl::viewSize() { - int width, height; - evas_object_geometry_get(m_viewWidget, 0, 0, &width, &height); - return IntSize(width, height); + return ewk_view_size_get(m_viewWidget); } bool PageClientImpl::isViewWindowActive() @@ -121,9 +123,9 @@ void PageClientImpl::toolTipChanged(const String&, const String&) notImplemented(); } -void PageClientImpl::setCursor(const Cursor&) +void PageClientImpl::setCursor(const Cursor& cursor) { - notImplemented(); + ewk_view_cursor_set(m_viewWidget, cursor); } void PageClientImpl::setCursorHiddenUntilMouseMoves(bool) @@ -221,12 +223,12 @@ void PageClientImpl::setFindIndicator(PassRefPtr<FindIndicator>, bool, bool) #if USE(ACCELERATED_COMPOSITING) void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext&) { - notImplemented(); + ewk_view_accelerated_compositing_mode_enter(m_viewWidget); } void PageClientImpl::exitAcceleratedCompositingMode() { - notImplemented(); + ewk_view_accelerated_compositing_mode_exit(m_viewWidget); } void PageClientImpl::updateAcceleratedCompositingMode(const LayerTreeContext&) @@ -276,4 +278,21 @@ void PageClientImpl::countStringMatchesInCustomRepresentation(const String&, Fin notImplemented(); } +void PageClientImpl::handleDownloadRequest(DownloadProxy* download) +{ + Ewk_Download_Job* ewkDownload = ewk_download_job_new(download, m_viewWidget); + // For now we only support one default context, but once we support + // multiple contexts, we will need to retrieve the context from the + // view. + ewk_context_download_job_add(ewk_context_default_get(), ewkDownload); + ewk_download_job_unref(ewkDownload); +} + +#if USE(TILED_BACKING_STORE) +void PageClientImpl::pageDidRequestScroll(const IntPoint&) +{ + notImplemented(); +} +#endif + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h index 427ef5297..1bd22934a 100644 --- a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h +++ b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h @@ -76,6 +76,8 @@ private: virtual WebCore::IntPoint screenToWindow(const WebCore::IntPoint&); virtual WebCore::IntRect windowToScreen(const WebCore::IntRect&); + virtual void handleDownloadRequest(DownloadProxy*); + virtual void doneWithKeyEvent(const NativeWebKeyboardEvent&, bool); #if ENABLE(TOUCH_EVENTS) virtual void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled); @@ -106,6 +108,10 @@ private: virtual void findStringInCustomRepresentation(const String&, FindOptions, unsigned); virtual void countStringMatchesInCustomRepresentation(const String&, FindOptions, unsigned); +#if USE(TILED_BACKING_STORE) + virtual void pageDidRequestScroll(const WebCore::IntPoint&); +#endif + private: RefPtr<WebPageProxy> m_page; Evas_Object* m_viewWidget; diff --git a/Source/WebKit2/UIProcess/API/efl/VibrationProvider.cpp b/Source/WebKit2/UIProcess/API/efl/VibrationProvider.cpp new file mode 100644 index 000000000..a96910638 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/VibrationProvider.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "VibrationProvider.h" + +#if ENABLE(VIBRATION) + +#include "WKAPICast.h" +#include "WKVibration.h" +#include <Evas.h> + +using namespace WebCore; + +/** + * \struct _Ewk_Vibration_Client + * @brief Contains the vibration client callbacks. + */ +struct _Ewk_Vibration_Client { + Ewk_Vibration_Client_Vibrate_Cb vibrate; + Ewk_Vibration_Client_Vibration_Cancel_Cb cancelVibration; + void* userData; + + _Ewk_Vibration_Client(Ewk_Vibration_Client_Vibrate_Cb vibrate, Ewk_Vibration_Client_Vibration_Cancel_Cb cancelVibration, void* userData) + : vibrate(vibrate) + , cancelVibration(cancelVibration) + , userData(userData) + { } +}; + +static inline VibrationProvider* toVibrationProvider(const void* clientInfo) +{ + return static_cast<VibrationProvider*>(const_cast<void*>(clientInfo)); +} + +static void vibrateCallback(WKVibrationRef vibrationRef, uint64_t vibrationTime, const void* clientInfo) +{ + toVibrationProvider(clientInfo)->vibrate(vibrationTime); +} + +static void cancelVibrationCallback(WKVibrationRef vibrationRef, const void* clientInfo) +{ + toVibrationProvider(clientInfo)->cancelVibration(); +} + +PassRefPtr<VibrationProvider> VibrationProvider::create(WKVibrationRef wkVibrationRef) +{ + return adoptRef(new VibrationProvider(wkVibrationRef)); +} + +VibrationProvider::VibrationProvider(WKVibrationRef wkVibrationRef) + : m_wkVibrationRef(wkVibrationRef) +{ + ASSERT(wkVibrationRef); + + WKVibrationProvider wkVibrationProvider = { + kWKVibrationProviderCurrentVersion, + this, // clientInfo + vibrateCallback, + cancelVibrationCallback + }; + WKVibrationSetProvider(m_wkVibrationRef.get(), &wkVibrationProvider); +} + +VibrationProvider::~VibrationProvider() +{ +} + +void VibrationProvider::vibrate(uint64_t vibrationTime) +{ + if (m_vibrationClient && m_vibrationClient->vibrate) + m_vibrationClient->vibrate(vibrationTime, m_vibrationClient->userData); +} + +void VibrationProvider::cancelVibration() +{ + if (m_vibrationClient && m_vibrationClient->cancelVibration) + m_vibrationClient->cancelVibration(m_vibrationClient->userData); +} + +void VibrationProvider::setVibrationClientCallbacks(Ewk_Vibration_Client_Vibrate_Cb vibrate, Ewk_Vibration_Client_Vibration_Cancel_Cb cancelVibration, void* data) +{ + m_vibrationClient = adoptPtr(new Ewk_Vibration_Client(vibrate, cancelVibration, data)); +} + +#endif // ENABLE(VIBRATION) diff --git a/Source/WebKit2/UIProcess/API/efl/VibrationProvider.h b/Source/WebKit2/UIProcess/API/efl/VibrationProvider.h new file mode 100644 index 000000000..c2643b638 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/VibrationProvider.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VibrationProvider_h +#define VibrationProvider_h + +#if ENABLE(VIBRATION) + +#include "WKRetainPtr.h" +#include "ewk_context.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +typedef struct _Ewk_Vibration_Client Ewk_Vibration_Client; + +class VibrationProvider : public RefCounted<VibrationProvider> { +public: + static PassRefPtr<VibrationProvider> create(WKVibrationRef); + virtual ~VibrationProvider(); + + void vibrate(uint64_t vibrationTime); + void cancelVibration(); + void setVibrationClientCallbacks(Ewk_Vibration_Client_Vibrate_Cb, Ewk_Vibration_Client_Vibration_Cancel_Cb, void*); + +private: + explicit VibrationProvider(WKVibrationRef); + + WKRetainPtr<WKVibrationRef> m_wkVibrationRef; + OwnPtr<Ewk_Vibration_Client> m_vibrationClient; +}; + +#endif // ENABLE(VIBRATION) + +#endif // VibrationProvider_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_context.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_context.cpp index b8607e584..f2ed417fc 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_context.cpp +++ b/Source/WebKit2/UIProcess/API/efl/ewk_context.cpp @@ -22,13 +22,17 @@ #include "ewk_context.h" #include "BatteryProvider.h" +#include "VibrationProvider.h" #include "WKAPICast.h" #include "WKContextSoup.h" #include "WKRetainPtr.h" #include "WKString.h" +#include "ewk_context_download_client_private.h" #include "ewk_context_private.h" #include "ewk_context_request_manager_client_private.h" #include "ewk_cookie_manager_private.h" +#include "ewk_download_job.h" +#include "ewk_download_job_private.h" #include <wtf/HashMap.h> #include <wtf/text/WTFString.h> @@ -58,6 +62,10 @@ struct _Ewk_Context { #if ENABLE(BATTERY_STATUS) RefPtr<BatteryProvider> batteryProvider; #endif +#if ENABLE(VIBRATION) + RefPtr<VibrationProvider> vibrationProvider; +#endif + HashMap<uint64_t, Ewk_Download_Job*> downloadJobs; WKRetainPtr<WKSoupRequestManagerRef> requestManager; URLSchemeHandlerMap urlSchemeHandlers; @@ -72,13 +80,24 @@ struct _Ewk_Context { batteryProvider = BatteryProvider::create(wkBatteryManager); #endif +#if ENABLE(VIBRATION) + WKVibrationRef wkVibrationRef = WKContextGetVibration(contextRef); + vibrationProvider = VibrationProvider::create(wkVibrationRef); +#endif + ewk_context_request_manager_client_attach(this); + ewk_context_download_client_attach(this); } ~_Ewk_Context() { if (cookieManager) ewk_cookie_manager_free(cookieManager); + + HashMap<uint64_t, Ewk_Download_Job*>::iterator it = downloadJobs.begin(); + HashMap<uint64_t, Ewk_Download_Job*>::iterator end = downloadJobs.end(); + for ( ; it != end; ++it) + ewk_download_job_unref(it->second); } }; @@ -99,6 +118,47 @@ WKContextRef ewk_context_WKContext_get(const Ewk_Context* ewkContext) /** * @internal + * Registers that a new download has been requested. + */ +void ewk_context_download_job_add(Ewk_Context* ewkContext, Ewk_Download_Job* ewkDownload) +{ + EINA_SAFETY_ON_NULL_RETURN(ewkContext); + EINA_SAFETY_ON_NULL_RETURN(ewkDownload); + + uint64_t downloadId = ewk_download_job_id_get(ewkDownload); + if (ewkContext->downloadJobs.contains(downloadId)) + return; + + ewk_download_job_ref(ewkDownload); + ewkContext->downloadJobs.add(downloadId, ewkDownload); +} + +/** + * @internal + * Returns the #Ewk_Download_Job with the given @a downloadId, or + * @c 0 in case of failure. + */ +Ewk_Download_Job* ewk_context_download_job_get(const Ewk_Context* ewkContext, uint64_t downloadId) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(ewkContext, 0); + + return ewkContext->downloadJobs.get(downloadId); +} + +/** + * @internal + * Removes the #Ewk_Download_Job with the given @a downloadId from the internal + * HashMap. + */ +void ewk_context_download_job_remove(Ewk_Context* ewkContext, uint64_t downloadId) +{ + EINA_SAFETY_ON_NULL_RETURN(ewkContext); + Ewk_Download_Job* download = ewkContext->downloadJobs.take(downloadId); + if (download) + ewk_download_job_unref(download); +} + +/** * Retrieve the request manager for @a ewkContext. * * @param ewkContext a #Ewk_Context object. @@ -151,3 +211,12 @@ Eina_Bool ewk_context_uri_scheme_register(Ewk_Context* ewkContext, const char* s return true; } + +void ewk_context_vibration_client_callbacks_set(Ewk_Context* ewkContext, Ewk_Vibration_Client_Vibrate_Cb vibrate, Ewk_Vibration_Client_Vibration_Cancel_Cb cancel, void* data) +{ + EINA_SAFETY_ON_NULL_RETURN(ewkContext); + +#if ENABLE(VIBRATION) + ewkContext->vibrationProvider->setVibrationClientCallbacks(vibrate, cancel, data); +#endif +} diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_context.h b/Source/WebKit2/UIProcess/API/efl/ewk_context.h index 3df362f6f..5e4d34262 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_context.h +++ b/Source/WebKit2/UIProcess/API/efl/ewk_context.h @@ -47,6 +47,20 @@ typedef struct _Ewk_Context Ewk_Context; typedef void (*Ewk_Url_Scheme_Request_Cb) (Ewk_Url_Scheme_Request *request, void *user_data); /** + * @typedef Ewk_Vibration_Client_Vibrate_Cb Ewk_Vibration_Client_Vibrate_Cb + * @brief Type definition for a function that will be called back when vibrate + * request receiveed from the vibration controller. + */ +typedef void (*Ewk_Vibration_Client_Vibrate_Cb)(uint64_t vibration_time, void *user_data); + +/** + * @typedef Ewk_Vibration_Client_Vibration_Cancel_Cb Ewk_Vibration_Client_Vibration_Cancel_Cb + * @brief Type definition for a function that will be called back when cancel + * vibration request receiveed from the vibration controller. + */ +typedef void (*Ewk_Vibration_Client_Vibration_Cancel_Cb)(void *user_data); + +/** * Gets default Ewk_Context instance. * * @return Ewk_Context object. @@ -105,6 +119,22 @@ EAPI Ewk_Cookie_Manager *ewk_context_cookie_manager_get(const Ewk_Context *conte */ EAPI Eina_Bool ewk_context_uri_scheme_register(Ewk_Context *context, const char *scheme, Ewk_Url_Scheme_Request_Cb callback, void *user_data); +/** + * Sets vibration client callbacks to handle the tactile feedback in the form of + * vibration in the client application when the content asks for vibration. + * + * To stop listening for vibration events, you may call this function with @c + * NULL for the callbacks. + * + * @param context context object to set vibration client callbacks. + * @param vibrate The function to call when the vibrate request received from the + * controller (may be @c NULL). + * @param cancel The function to call when the cancel vibration request received + * from the controller (may be @c NULL). + * @param data User data (may be @c NULL). + */ +EAPI void ewk_context_vibration_client_callbacks_set(Ewk_Context *context, Ewk_Vibration_Client_Vibrate_Cb vibrate, Ewk_Vibration_Client_Vibration_Cancel_Cb cancel, void *data); + #ifdef __cplusplus } #endif diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_context_download_client.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_context_download_client.cpp new file mode 100644 index 000000000..1cb7e17f2 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_context_download_client.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "DownloadProxy.h" +#include "WKAPICast.h" +#include "WKContext.h" +#include "WKString.h" +#include "ewk_context_download_client_private.h" +#include "ewk_context_private.h" +#include "ewk_download_job.h" +#include "ewk_download_job_private.h" +#include "ewk_url_response.h" +#include "ewk_url_response_private.h" +#include "ewk_view_private.h" +#include "ewk_web_error.h" +#include "ewk_web_error_private.h" +#include <string.h> +#include <wtf/text/CString.h> + +using namespace WebKit; + +static inline Ewk_Context* toEwkContext(const void* clientInfo) +{ + return static_cast<Ewk_Context*>(const_cast<void*>(clientInfo)); +} + +static WKStringRef decideDestinationWithSuggestedFilename(WKContextRef, WKDownloadRef wkDownload, WKStringRef filename, bool* allowOverwrite, const void* clientInfo) +{ + Ewk_Download_Job* download = ewk_context_download_job_get(toEwkContext(clientInfo), toImpl(wkDownload)->downloadID()); + ASSERT(download); + + ewk_download_job_suggested_filename_set(download, toImpl(filename)->string().utf8().data()); + + // We send the new download signal on the Ewk_View only once we have received the response + // and the suggested file name. + ewk_view_download_job_requested(ewk_download_job_view_get(download), download); + + // DownloadSoup expects the destination to be a URI. + String destination = String("file://") + String::fromUTF8(ewk_download_job_destination_get(download)); + + return WKStringCreateWithUTF8CString(destination.utf8().data()); +} + +static void didReceiveResponse(WKContextRef, WKDownloadRef wkDownload, WKURLResponseRef wkResponse, const void* clientInfo) +{ + Ewk_Download_Job* download = ewk_context_download_job_get(toEwkContext(clientInfo), toImpl(wkDownload)->downloadID()); + ASSERT(download); + Ewk_Url_Response* response = ewk_url_response_new(toImpl(wkResponse)->resourceResponse()); + ewk_download_job_response_set(download, response); + ewk_url_response_unref(response); +} + +static void didCreateDestination(WKContextRef, WKDownloadRef wkDownload, WKStringRef path, const void* clientInfo) +{ + Ewk_Download_Job* download = ewk_context_download_job_get(toEwkContext(clientInfo), toImpl(wkDownload)->downloadID()); + ASSERT(download); + + ewk_download_job_state_set(download, EWK_DOWNLOAD_JOB_STATE_DOWNLOADING); +} + +static void didReceiveData(WKContextRef, WKDownloadRef wkDownload, uint64_t length, const void* clientInfo) +{ + Ewk_Download_Job* download = ewk_context_download_job_get(toEwkContext(clientInfo), toImpl(wkDownload)->downloadID()); + ASSERT(download); + ewk_download_job_received_data(download, length); +} + +static void didFail(WKContextRef, WKDownloadRef wkDownload, WKErrorRef error, const void *clientInfo) +{ + uint64_t downloadId = toImpl(wkDownload)->downloadID(); + Ewk_Download_Job* download = ewk_context_download_job_get(toEwkContext(clientInfo), downloadId); + ASSERT(download); + + Ewk_Web_Error* ewkError = ewk_web_error_new(error); + ewk_download_job_state_set(download, EWK_DOWNLOAD_JOB_STATE_FAILED); + ewk_view_download_job_failed(ewk_download_job_view_get(download), download, ewkError); + ewk_web_error_free(ewkError); + ewk_context_download_job_remove(toEwkContext(clientInfo), downloadId); +} + +static void didCancel(WKContextRef, WKDownloadRef wkDownload, const void *clientInfo) +{ + uint64_t downloadId = toImpl(wkDownload)->downloadID(); + Ewk_Download_Job* download = ewk_context_download_job_get(toEwkContext(clientInfo), downloadId); + ASSERT(download); + + ewk_download_job_state_set(download, EWK_DOWNLOAD_JOB_STATE_CANCELLED); + ewk_view_download_job_cancelled(ewk_download_job_view_get(download), download); + ewk_context_download_job_remove(toEwkContext(clientInfo), downloadId); +} + +static void didFinish(WKContextRef, WKDownloadRef wkDownload, const void *clientInfo) +{ + uint64_t downloadId = toImpl(wkDownload)->downloadID(); + Ewk_Download_Job* download = ewk_context_download_job_get(toEwkContext(clientInfo), downloadId); + ASSERT(download); + + ewk_download_job_state_set(download, EWK_DOWNLOAD_JOB_STATE_FINISHED); + ewk_view_download_job_finished(ewk_download_job_view_get(download), download); + ewk_context_download_job_remove(toEwkContext(clientInfo), downloadId); +} + +void ewk_context_download_client_attach(Ewk_Context* ewkContext) +{ + WKContextDownloadClient wkDownloadClient; + memset(&wkDownloadClient, 0, sizeof(WKContextDownloadClient)); + + wkDownloadClient.version = kWKContextDownloadClientCurrentVersion; + wkDownloadClient.clientInfo = ewkContext; + wkDownloadClient.didCancel = didCancel; + wkDownloadClient.decideDestinationWithSuggestedFilename = decideDestinationWithSuggestedFilename; + wkDownloadClient.didCreateDestination = didCreateDestination; + wkDownloadClient.didReceiveResponse = didReceiveResponse; + wkDownloadClient.didReceiveData = didReceiveData; + wkDownloadClient.didFail = didFail; + wkDownloadClient.didFinish = didFinish; + + WKContextSetDownloadClient(ewk_context_WKContext_get(ewkContext), &wkDownloadClient); +} + + diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_context_download_client_private.h b/Source/WebKit2/UIProcess/API/efl/ewk_context_download_client_private.h new file mode 100644 index 000000000..f7017a863 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_context_download_client_private.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ewk_context_download_client_private_h +#define ewk_context_download_client_private_h + +typedef struct _Ewk_Context Ewk_Context; + +void ewk_context_download_client_attach(Ewk_Context*); + +#endif // ewk_context_download_client_private_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_context_private.h b/Source/WebKit2/UIProcess/API/efl/ewk_context_private.h index d78e1e961..db9e911d2 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_context_private.h +++ b/Source/WebKit2/UIProcess/API/efl/ewk_context_private.h @@ -23,10 +23,15 @@ #include <WebKit2/WKBase.h> typedef struct _Ewk_Context Ewk_Context; +typedef struct _Ewk_Download_Job Ewk_Download_Job; typedef struct _Ewk_Url_Scheme_Request Ewk_Url_Scheme_Request; WKContextRef ewk_context_WKContext_get(const Ewk_Context*); WKSoupRequestManagerRef ewk_context_request_manager_get(const Ewk_Context*); void ewk_context_url_scheme_request_received(Ewk_Context*, Ewk_Url_Scheme_Request*); +void ewk_context_download_job_add(Ewk_Context*, Ewk_Download_Job*); +Ewk_Download_Job* ewk_context_download_job_get(const Ewk_Context*, uint64_t downloadId); +void ewk_context_download_job_remove(Ewk_Context*, uint64_t downloadId); + #endif // ewk_context_private_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_cookie_manager.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_cookie_manager.cpp index 02f1fbd76..45dd75e63 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_cookie_manager.cpp +++ b/Source/WebKit2/UIProcess/API/efl/ewk_cookie_manager.cpp @@ -40,16 +40,47 @@ using namespace WebKit; +struct Cookie_Change_Handler { + Ewk_Cookie_Manager_Changes_Watch_Cb callback; + void* userData; + + Cookie_Change_Handler() + : callback(0) + , userData(0) + { } + + Cookie_Change_Handler(Ewk_Cookie_Manager_Changes_Watch_Cb _callback, void* _userData) + : callback(_callback) + , userData(_userData) + { } +}; + +static void cookiesDidChange(WKCookieManagerRef, const void* clientInfo); + /** * \struct _Ewk_Cookie_Manager * @brief Contains the cookie manager data. */ struct _Ewk_Cookie_Manager { WKRetainPtr<WKCookieManagerRef> wkCookieManager; + Cookie_Change_Handler changeHandler; _Ewk_Cookie_Manager(WKCookieManagerRef cookieManagerRef) : wkCookieManager(cookieManagerRef) - { } + { + WKCookieManagerClient wkCookieManagerClient = { + kWKCookieManagerClientCurrentVersion, + this, // clientInfo + cookiesDidChange + }; + WKCookieManagerSetClient(wkCookieManager.get(), &wkCookieManagerClient); + } + + ~_Ewk_Cookie_Manager() + { + if (changeHandler.callback) + WKCookieManagerStopObservingCookieChanges(wkCookieManager.get()); + } }; #define EWK_COOKIE_MANAGER_WK_GET_OR_RETURN(manager, wkManager_, ...) \ @@ -72,12 +103,28 @@ COMPILE_ASSERT_MATCHING_ENUM(EWK_COOKIE_ACCEPT_POLICY_NO_THIRD_PARTY, kWKHTTPCoo COMPILE_ASSERT_MATCHING_ENUM(EWK_COOKIE_PERSISTENT_STORAGE_TEXT, SoupCookiePersistentStorageText); COMPILE_ASSERT_MATCHING_ENUM(EWK_COOKIE_PERSISTENT_STORAGE_SQLITE, SoupCookiePersistentStorageSQLite); +static void cookiesDidChange(WKCookieManagerRef, const void* clientInfo) +{ + Ewk_Cookie_Manager* manager = static_cast<Ewk_Cookie_Manager*>(const_cast<void*>(clientInfo)); + + if (!manager->changeHandler.callback) + return; + + manager->changeHandler.callback(manager->changeHandler.userData); +} + void ewk_cookie_manager_persistent_storage_set(Ewk_Cookie_Manager* manager, const char* filename, Ewk_Cookie_Persistent_Storage storage) { EWK_COOKIE_MANAGER_WK_GET_OR_RETURN(manager, wkManager); EINA_SAFETY_ON_NULL_RETURN(filename); + if (manager->changeHandler.callback) + WKCookieManagerStopObservingCookieChanges(wkManager); + toImpl(wkManager)->setCookiePersistentStorage(String::fromUTF8(filename), storage); + + if (manager->changeHandler.callback) + WKCookieManagerStartObservingCookieChanges(wkManager); } void ewk_cookie_manager_accept_policy_set(Ewk_Cookie_Manager* manager, Ewk_Cookie_Accept_Policy policy) @@ -174,6 +221,18 @@ void ewk_cookie_manager_cookies_clear(Ewk_Cookie_Manager* manager) WKCookieManagerDeleteAllCookies(wkManager); } +void ewk_cookie_manager_changes_watch(Ewk_Cookie_Manager* manager, Ewk_Cookie_Manager_Changes_Watch_Cb callback, void* data) +{ + EWK_COOKIE_MANAGER_WK_GET_OR_RETURN(manager, wkManager); + + manager->changeHandler = Cookie_Change_Handler(callback, data); + + if (callback) + WKCookieManagerStartObservingCookieChanges(wkManager); + else + WKCookieManagerStopObservingCookieChanges(wkManager); +} + /** * @internal * Frees a Ewk_Cookie_Manager object. diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_cookie_manager.h b/Source/WebKit2/UIProcess/API/efl/ewk_cookie_manager.h index e93ed8ed8..e37780864 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_cookie_manager.h +++ b/Source/WebKit2/UIProcess/API/efl/ewk_cookie_manager.h @@ -90,6 +90,12 @@ typedef void (*Ewk_Cookie_Manager_Async_Policy_Get_Cb)(Ewk_Cookie_Accept_Policy typedef void (*Ewk_Cookie_Manager_Async_Hostnames_Get_Cb)(Eina_List* hostnames, Ewk_Web_Error *error, void *event_info); /** + * @typedef Ewk_Cookie_Manager_Changes_Watch_Cb Ewk_Cookie_Manager_Changes_Watch_Cb + * @brief Callback type for use with ewk_cookie_manager_changes_watch() + */ +typedef void (*Ewk_Cookie_Manager_Changes_Watch_Cb)(void *event_info); + +/** * Set the @a filename where non-session cookies are stored persistently using @a storage as the format to read/write the cookies. * * Cookies are initially read from @filename to create an initial set of cookies. @@ -144,6 +150,17 @@ EAPI void ewk_cookie_manager_async_hostnames_with_cookies_get(const Ewk_Cookie_M EAPI void ewk_cookie_manager_hostname_cookies_clear(Ewk_Cookie_Manager *manager, const char *hostname); /** + * Watch for cookies changes in @a manager. + * + * Pass @c NULL as value for @a callback to stop watching for changes. + * + * @param manager The cookie manager to watch. + * @param callback function that will be called every time cookies are added, removed or modified. + * @param data User data (may be @c NULL). + */ +EAPI void ewk_cookie_manager_changes_watch(Ewk_Cookie_Manager *manager, Ewk_Cookie_Manager_Changes_Watch_Cb callback, void *data); + +/** * Delete all cookies of @a manager. * * @param manager The cookie manager to update. diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_download_job.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_download_job.cpp new file mode 100644 index 000000000..c41681071 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_download_job.cpp @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ewk_download_job.h" + +#include "DownloadProxy.h" +#include "WKAPICast.h" +#include "WKRetainPtr.h" +#include "WebURLRequest.h" +#include "ewk_download_job_private.h" +#include "ewk_url_request_private.h" +#include <Ecore.h> + +using namespace WebKit; + +/** + * \struct _Ewk_Download_Job + * @brief Contains the download data. + */ +struct _Ewk_Download_Job { + unsigned int __ref; /**< the reference count of the object */ + DownloadProxy* downloadProxy; + Evas_Object* view; + Ewk_Download_Job_State state; + Ewk_Url_Request* request; + Ewk_Url_Response* response; + double startTime; + double endTime; + uint64_t downloaded; /**< length already downloaded */ + const char* destination; + const char* suggestedFilename; + + _Ewk_Download_Job(DownloadProxy* download, Evas_Object* ewkView) + : __ref(1) + , downloadProxy(download) + , view(ewkView) + , state(EWK_DOWNLOAD_JOB_STATE_NOT_STARTED) + , request(0) + , response(0) + , startTime(-1) + , endTime(-1) + , downloaded(0) + , destination(0) + , suggestedFilename(0) + { } + + ~_Ewk_Download_Job() + { + ASSERT(!__ref); + if (request) + ewk_url_request_unref(request); + if (response) + ewk_url_response_unref(response); + eina_stringshare_del(destination); + eina_stringshare_del(suggestedFilename); + } +}; + +void ewk_download_job_ref(Ewk_Download_Job* download) +{ + EINA_SAFETY_ON_NULL_RETURN(download); + + ++download->__ref; +} + +void ewk_download_job_unref(Ewk_Download_Job* download) +{ + EINA_SAFETY_ON_NULL_RETURN(download); + + if (--download->__ref) + return; + + delete download; +} + +/** + * @internal + * Queries the identifier for this download + */ +uint64_t ewk_download_job_id_get(const Ewk_Download_Job* download) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(download, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(download->downloadProxy, 0); + + return download->downloadProxy->downloadID(); +} + +/** + * @internal + * Returns the view this download is attached to. + * The view is needed to send notification signals. + */ +Evas_Object* ewk_download_job_view_get(const Ewk_Download_Job* download) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(download, 0); + + return download->view; +} + +Ewk_Download_Job_State ewk_download_job_state_get(const Ewk_Download_Job* download) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(download, EWK_DOWNLOAD_JOB_STATE_UNKNOWN); + + return download->state; +} + +Ewk_Url_Request* ewk_download_job_request_get(const Ewk_Download_Job* download) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(download, 0); + + if (!download->request) { + EINA_SAFETY_ON_NULL_RETURN_VAL(download->downloadProxy, 0); + WKRetainPtr<WKURLRequestRef> wkURLRequest(AdoptWK, toAPI(WebURLRequest::create(download->downloadProxy->request()).leakRef())); + const_cast<Ewk_Download_Job*>(download)->request = ewk_url_request_new(wkURLRequest.get()); + } + + return download->request; +} + +Ewk_Url_Response* ewk_download_job_response_get(const Ewk_Download_Job* download) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(download, 0); + + return download->response; +} + +const char* ewk_download_job_destination_get(const Ewk_Download_Job* download) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(download, 0); + + return download->destination; +} + +Eina_Bool ewk_download_job_destination_set(Ewk_Download_Job* download, const char* destination) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(download, false); + EINA_SAFETY_ON_NULL_RETURN_VAL(destination, false); + + eina_stringshare_replace(&download->destination, destination); + + return true; +} + +const char *ewk_download_job_suggested_filename_get(const Ewk_Download_Job* download) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(download, 0); + + return download->suggestedFilename; +} + +Eina_Bool ewk_download_job_cancel(Ewk_Download_Job* download) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(download, false); + EINA_SAFETY_ON_NULL_RETURN_VAL(download->downloadProxy, false); + + if (download->state != EWK_DOWNLOAD_JOB_STATE_DOWNLOADING) + return false; + + download->state = EWK_DOWNLOAD_JOB_STATE_CANCELLING; + download->downloadProxy->cancel(); + return true; +} + +double ewk_download_job_estimated_progress_get(const Ewk_Download_Job* download) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(download, 0); + + if (!download->response) + return 0; + + const unsigned long contentLength = ewk_url_response_content_length_get(download->response); + if (!contentLength) + return 0; + + return static_cast<double>(download->downloaded) / contentLength; +} + +double ewk_download_job_elapsed_time_get(const Ewk_Download_Job* download) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(download, 0); + + // Download has not started yet. + if (download->startTime < 0) + return 0; + + // Download had ended, return the time elapsed between the + // download start and the end event. + if (download->endTime >= 0) + return download->endTime - download->startTime; + + // Download is still going. + return ecore_time_get() - download->startTime; +} + +/** + * @internal + * Sets the URL @a response for this @a download. + */ +void ewk_download_job_response_set(Ewk_Download_Job* download, Ewk_Url_Response* response) +{ + EINA_SAFETY_ON_NULL_RETURN(download); + EINA_SAFETY_ON_NULL_RETURN(response); + + ewk_url_response_ref(response); + download->response = response; +} + +/** + * @internal + * Sets the suggested file name for this @a download. + */ +void ewk_download_job_suggested_filename_set(Ewk_Download_Job* download, const char* suggestedFilename) +{ + EINA_SAFETY_ON_NULL_RETURN(download); + + eina_stringshare_replace(&download->suggestedFilename, suggestedFilename); +} + +/** + * @internal + * Report a given amount of data was received. + */ +void ewk_download_job_received_data(Ewk_Download_Job* download, uint64_t length) +{ + EINA_SAFETY_ON_NULL_RETURN(download); + + download->downloaded += length; +} + +/** + * @internal + * Sets the state of the download. + */ +void ewk_download_job_state_set(Ewk_Download_Job* download, Ewk_Download_Job_State state) +{ + download->state = state; + + // Update start time if the download has started + if (state == EWK_DOWNLOAD_JOB_STATE_DOWNLOADING) + download->startTime = ecore_time_get(); + + // Update end time if the download has finished (successfully or not) + if (state == EWK_DOWNLOAD_JOB_STATE_FAILED + || state == EWK_DOWNLOAD_JOB_STATE_CANCELLED + || state == EWK_DOWNLOAD_JOB_STATE_FINISHED) + download->endTime = ecore_time_get(); +} + +/** + * @internal + * Constructs a Ewk_Download_Job from a DownloadProxy. + */ +Ewk_Download_Job* ewk_download_job_new(DownloadProxy* download, Evas_Object* ewkView) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(download, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(ewkView, 0); + + return new _Ewk_Download_Job(download, ewkView); +} diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_download_job.h b/Source/WebKit2/UIProcess/API/efl/ewk_download_job.h new file mode 100644 index 000000000..68f03fc7e --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_download_job.h @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file ewk_download_job.h + * @brief Describes the Download Job API. + * + * @note Ewk_Download_Job encapsulates a WebKit download job in order to provide + * information about it and interact with it (e.g. set the destination + * path, cancel the download, ...). + */ + +#ifndef ewk_download_job_h +#define ewk_download_job_h + +#include "ewk_url_request.h" +#include "ewk_url_response.h" +#include <Eina.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** Creates a type name for _Ewk_Download_Job_Job */ +typedef struct _Ewk_Download_Job Ewk_Download_Job; + +/// Defines the possible states of a download. +enum _Ewk_Download_Job_State { + /// The download state is unknown + EWK_DOWNLOAD_JOB_STATE_UNKNOWN = -1, + /// The download has not started yet + EWK_DOWNLOAD_JOB_STATE_NOT_STARTED, + /// The download has started + EWK_DOWNLOAD_JOB_STATE_DOWNLOADING, + /// The download stopped because of a failure + EWK_DOWNLOAD_JOB_STATE_FAILED, + /// The download is being cancelled + EWK_DOWNLOAD_JOB_STATE_CANCELLING, + /// The download stopped because it was cancelled + EWK_DOWNLOAD_JOB_STATE_CANCELLED, + /// The download completed successfully. + EWK_DOWNLOAD_JOB_STATE_FINISHED +}; +/// Creates a type name for @a _Ewk_Download_Job_State. +typedef enum _Ewk_Download_Job_State Ewk_Download_Job_State; + +/** + * Increases the reference count of the given object. + * + * @param download the download object to increase the reference count + */ +EAPI void ewk_download_job_ref(Ewk_Download_Job *download); + +/** + * Decreases the reference count of the given object, possibly freeing it. + * + * When the reference count reaches 0, the download is freed. + * + * @param download the download object to decrease the reference count + */ +EAPI void ewk_download_job_unref(Ewk_Download_Job *download); + +/** + * Query the state for this download. + * + * @param download a #Ewk_Download_Job to query. + * + * @return the download state. + */ +EAPI Ewk_Download_Job_State ewk_download_job_state_get(const Ewk_Download_Job *download); + +/** + * Query the URL request for this download. + * + * @param download a #Ewk_Download_Job to query. + * + * @return the #Ewk_Url_Request for this download. + */ +EAPI Ewk_Url_Request *ewk_download_job_request_get(const Ewk_Download_Job *download); + +/** + * Query the URL response for this download. + * + * @param download a #Ewk_Download_Job to query. + * + * @return the #Ewk_Url_Response for this download or @c NULL if it was not received yet. + */ +EAPI Ewk_Url_Response *ewk_download_job_response_get(const Ewk_Download_Job *download); + +/** + * Query the URI to which the downloaded file will be written. + * + * @param download a #Ewk_Download_Job to query. + * + * @return the destination pointer, that may be @c NULL. This pointer is + * guaranteed to be eina_stringshare, so whenever possible + * save yourself some cpu cycles and use + * eina_stringshare_ref() instead of eina_stringshare_add() or + * strdup(). + */ +EAPI const char *ewk_download_job_destination_get(const Ewk_Download_Job *download); + +/** + * Sets the destination path for this download. + * + * Sets the path to which the downloaded file will be written. + * + * This method needs to be called before the download transfer + * starts, by connecting to the "download,new" signal on the + * Ewk_View and setting the destination in the callback. To set + * the destination using the filename suggested by the server + * use ewk_download_job_suggested_filename_get(). + * + * @param download #Ewk_Download_Job to update. + * @param destination the destination path. + * + * @return @c EINA_TRUE if successful, @c EINA_FALSE otherwise. + * + * @see ewk_download_job_suggested_filename_get + */ +EAPI Eina_Bool ewk_download_job_destination_set(Ewk_Download_Job *download, const char *destination); + +/** + * Queries the suggested file name for this download. + * + * It can be useful to use the value returned by this function to construct + * the destination path to pass to ewk_download_job_destination_set(). + * + * @param download #Ewk_Download_Job to query. + * + * @return The suggested file name for this download. This pointer is + * guaranteed to be eina_stringshare, so whenever possible + * save yourself some cpu cycles and use + * eina_stringshare_ref() instead of eina_stringshare_add() or + * strdup(). + * + * @see ewk_download_job_destination_set + */ +EAPI const char *ewk_download_job_suggested_filename_get(const Ewk_Download_Job *download); + +/** + * Cancels the download asynchronously. + * + * When the ongoing download operation is effectively cancelled a "download,cancelled" + * signal will be emitted on the view. + * + * @param download a #Ewk_Download_Job to cancel. + * + * @return @c EINA_TRUE if the cancellation request was taken into account, or + * @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool ewk_download_job_cancel(Ewk_Download_Job *download); + +/** + * Query the estimated progress for this download. + * + * @param download a #Ewk_Download_Job to query. + * + * @return an estimate of the of the percent complete for a download + * as a range from 0.0 to 1.0. + */ +EAPI double ewk_download_job_estimated_progress_get(const Ewk_Download_Job *download); + +/** + * Gets the elapsed time in seconds, including any fractional part. + * + * If the download finished, had an error or was cancelled this is + * the time between its start and the event. + * + * @param download a #Ewk_Download_Job + * + * @return seconds since the download was started or 0.0 in case of failure. + */ +EAPI double ewk_download_job_elapsed_time_get(const Ewk_Download_Job *download); + +#ifdef __cplusplus +} +#endif + +#endif // ewk_download_job_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_download_job_private.h b/Source/WebKit2/UIProcess/API/efl/ewk_download_job_private.h new file mode 100644 index 000000000..d043494c3 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_download_job_private.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ewk_download_job_private_h +#define ewk_download_job_private_h + +#include "WKBase.h" +#include <Evas.h> + +typedef struct _Ewk_Download_Job Ewk_Download_Job; +typedef struct _Ewk_Url_Response Ewk_Url_Response; +typedef struct _Ewk_Web_Error Ewk_Web_Error; + +namespace WebKit { +class DownloadProxy; +} + +Ewk_Download_Job* ewk_download_job_new(WebKit::DownloadProxy*, Evas_Object* ewkView); +uint64_t ewk_download_job_id_get(const Ewk_Download_Job*); +Evas_Object* ewk_download_job_view_get(const Ewk_Download_Job*); + +void ewk_download_job_state_set(Ewk_Download_Job*, Ewk_Download_Job_State); +void ewk_download_job_cancelled(Ewk_Download_Job*); +void ewk_download_job_failed(Ewk_Download_Job*); +void ewk_download_job_finished(Ewk_Download_Job*); +void ewk_download_job_started(Ewk_Download_Job*); + +void ewk_download_job_received_data(Ewk_Download_Job*, uint64_t length); +void ewk_download_job_response_set(Ewk_Download_Job*, Ewk_Url_Response*); +void ewk_download_job_suggested_filename_set(Ewk_Download_Job*, const char* suggestedFilename); + +#endif // ewk_download_job_private_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_form_submission_request.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_form_submission_request.cpp new file mode 100644 index 000000000..70721735b --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_form_submission_request.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ewk_form_submission_request.h" + +#include "WKAPICast.h" +#include "WKArray.h" +#include "WKBase.h" +#include "WKDictionary.h" +#include "WKFormSubmissionListener.h" +#include "WKRetainPtr.h" +#include "WKString.h" +#include "ewk_form_submission_request_private.h" +#include <wtf/text/CString.h> + +using namespace WebKit; + +/** + * \struct _Ewk_Form_Submission_Request + * @brief Contains the form submission request data. + */ +struct _Ewk_Form_Submission_Request { + unsigned int __ref; /**< the reference count of the object */ + WKRetainPtr<WKDictionaryRef> wkValues; + WKRetainPtr<WKFormSubmissionListenerRef> wkListener; + bool handledRequest; + + _Ewk_Form_Submission_Request(WKDictionaryRef values, WKFormSubmissionListenerRef listener) + : __ref(1) + , wkValues(values) + , wkListener(listener) + , handledRequest(false) + { } + + ~_Ewk_Form_Submission_Request() + { + ASSERT(!__ref); + + // Make sure the request is always handled before destroying. + if (!handledRequest) + WKFormSubmissionListenerContinue(wkListener.get()); + } +}; + +void ewk_form_submission_request_ref(Ewk_Form_Submission_Request* request) +{ + EINA_SAFETY_ON_NULL_RETURN(request); + ++request->__ref; +} + +void ewk_form_submission_request_unref(Ewk_Form_Submission_Request* request) +{ + EINA_SAFETY_ON_NULL_RETURN(request); + + if (--request->__ref) + return; + + delete request; +} + +Eina_List* ewk_form_submission_request_field_names_get(Ewk_Form_Submission_Request* request) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(request, 0); + + Eina_List* names = 0; + + WKRetainPtr<WKArrayRef> wkKeys(AdoptWK, WKDictionaryCopyKeys(request->wkValues.get())); + const size_t numKeys = WKArrayGetSize(wkKeys.get()); + for (size_t i = 0; i < numKeys; ++i) { + WKStringRef wkKey = static_cast<WKStringRef>(WKArrayGetItemAtIndex(wkKeys.get(), i)); + names = eina_list_append(names, eina_stringshare_add(toImpl(wkKey)->string().utf8().data())); + } + + return names; +} + +const char* ewk_form_submission_request_field_value_get(Ewk_Form_Submission_Request* request, const char* name) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(request, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(name, 0); + + WKRetainPtr<WKStringRef> wkKey(AdoptWK, WKStringCreateWithUTF8CString(name)); + WKStringRef wkValue = static_cast<WKStringRef>(WKDictionaryGetItemForKey(request->wkValues.get(), wkKey.get())); + + return wkValue ? eina_stringshare_add(toImpl(wkValue)->string().utf8().data()) : 0; +} + +Eina_Bool ewk_form_submission_request_submit(Ewk_Form_Submission_Request* request) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(request, false); + + WKFormSubmissionListenerContinue(request->wkListener.get()); + request->handledRequest = true; + + return true; +} + +/** + * @internal ewk_form_submission_request_new + * Creates a Ewk_Form_Submission_Request from a dictionary and a WKFormSubmissionListenerRef. + */ +Ewk_Form_Submission_Request* ewk_form_submission_request_new(WKDictionaryRef values, WKFormSubmissionListenerRef listener) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(values, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(listener, 0); + + return new Ewk_Form_Submission_Request(values, listener); +} diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_form_submission_request.h b/Source/WebKit2/UIProcess/API/efl/ewk_form_submission_request.h new file mode 100644 index 000000000..fa67e9360 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_form_submission_request.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file ewk_form_submission_request.h + * @brief Describes the Ewk Form Submission Request API. + * + * @note Ewk_Form_Submission_Request provides information regarding + * a form about the be submitted, in particular its text fields. + */ + +#ifndef ewk_form_submission_request_h +#define ewk_form_submission_request_h + +#include <Eina.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** Creates a type name for _Ewk_Form_Submission_Request */ +typedef struct _Ewk_Form_Submission_Request Ewk_Form_Submission_Request; + +/** + * Increases the reference count of the given object. + * + * @param request the request object to increase the reference count + */ +EAPI void ewk_form_submission_request_ref(Ewk_Form_Submission_Request *request); + +/** + * Decreases the reference count of the given object, possibly freeing it. + * + * When the reference count reaches 0, the request is freed. + * + * If the reference count reaches 0 and the form request has not be submitted yet, + * ewk_form_submission_request_submit() will be called automatically before + * destruction. + * + * @param request the request object to decrease the reference count + */ +EAPI void ewk_form_submission_request_unref(Ewk_Form_Submission_Request *request); + +/** + * Returns the list of field names contained in the form associated to @a request. + * + * @param request the request object to query. + * + * @return a #Eina_List with the form text fields names, or @c NULL in case of error. + * The items of the list are guaranteed to be stringshared so use eina_stringshare_add() + * instead of strdup() to copy them and free them using eina_stringshare_del(). + * + * @see ewk_form_submission_request_field_value_get() + */ +EAPI Eina_List *ewk_form_submission_request_field_names_get(Ewk_Form_Submission_Request *request); + +/** + * Returns the value of specific field contained in the form associated to @a request. + * + * @param request the request object to query. + * @param name name of the field to query the value for. + * + * @return a #Eina_List with the form text fields names, or @c NULL in case of error. + * The string returned is guaranteed to be stringshared. You need to call + * eina_stringshare_del() on the returned value once you are done with it. + * + * @see ewk_form_submission_request_field_names_get() + */ +EAPI const char *ewk_form_submission_request_field_value_get(Ewk_Form_Submission_Request *request, const char *name); + +/** + * Continues the form request submission. + * + * If you don't call this function explicitly, the form request will be submitted + * upon @a request object destruction. + * + * @param request the request object to submit. + * + * @return @c EINA_TRUE is if successful, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool ewk_form_submission_request_submit(Ewk_Form_Submission_Request *request); + +#ifdef __cplusplus +} +#endif + +#endif // ewk_form_submission_request_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_form_submission_request_private.h b/Source/WebKit2/UIProcess/API/efl/ewk_form_submission_request_private.h new file mode 100644 index 000000000..feb3d606b --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_form_submission_request_private.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ewk_form_submission_request_private_h +#define ewk_form_submission_request_private_h + +typedef struct _Ewk_Form_Submission_Request Ewk_Form_Submission_Request; + +Ewk_Form_Submission_Request* ewk_form_submission_request_new(WKDictionaryRef values, WKFormSubmissionListenerRef); + +#endif // ewk_form_submission_request_private_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_intent.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_intent.cpp index 7322108be..856179346 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_intent.cpp +++ b/Source/WebKit2/UIProcess/API/efl/ewk_intent.cpp @@ -156,7 +156,7 @@ Eina_List* ewk_intent_suggestions_get(const Ewk_Intent* intent) const size_t numSuggestions = WKArrayGetSize(wkSuggestions.get()); for (size_t i = 0; i < numSuggestions; ++i) { WKURLRef wkSuggestion = static_cast<WKURLRef>(WKArrayGetItemAtIndex(wkSuggestions.get(), i)); - listOfSuggestions = eina_list_append(listOfSuggestions, strdup(toImpl(wkSuggestion)->string().utf8().data())); + listOfSuggestions = eina_list_append(listOfSuggestions, eina_stringshare_add(toImpl(wkSuggestion)->string().utf8().data())); } return listOfSuggestions; @@ -165,7 +165,7 @@ Eina_List* ewk_intent_suggestions_get(const Ewk_Intent* intent) #endif } -char* ewk_intent_extra_get(const Ewk_Intent* intent, const char* key) +const char* ewk_intent_extra_get(const Ewk_Intent* intent, const char* key) { #if ENABLE(WEB_INTENTS) EWK_INTENT_WK_GET_OR_RETURN(intent, wkIntent, 0); @@ -176,7 +176,7 @@ char* ewk_intent_extra_get(const Ewk_Intent* intent, const char* key) if (value.isEmpty()) return 0; - return strdup(value.utf8().data()); + return eina_stringshare_add(value.utf8().data()); #else return 0; #endif @@ -193,7 +193,7 @@ Eina_List* ewk_intent_extra_names_get(const Ewk_Intent* intent) const size_t numKeys = WKArrayGetSize(wkKeys.get()); for (size_t i = 0; i < numKeys; ++i) { WKStringRef wkKey = static_cast<WKStringRef>(WKArrayGetItemAtIndex(wkKeys.get(), i)); - listOfKeys = eina_list_append(listOfKeys, strdup(toImpl(wkKey)->string().utf8().data())); + listOfKeys = eina_list_append(listOfKeys, eina_stringshare_add(toImpl(wkKey)->string().utf8().data())); } return listOfKeys; diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_intent.h b/Source/WebKit2/UIProcess/API/efl/ewk_intent.h index ae73c6ce5..abcffa59f 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_intent.h +++ b/Source/WebKit2/UIProcess/API/efl/ewk_intent.h @@ -104,29 +104,33 @@ EAPI const char *ewk_intent_service_get(const Ewk_Intent *intent); * @param intent intent item to query. * * @return @c Eina_List with suggested service URLs on success, or @c NULL on failure, - * the Eina_List and its items should be freed after use. Use free() to free the - * items. + * the Eina_List and its items should be freed after use. Use eina_stringshare_del() + * to free the items. */ EAPI Eina_List *ewk_intent_suggestions_get(const Ewk_Intent *intent); /** * Retrieves the value (if any) from the extra data dictionary this intent was constructed with. * + * The returned string should be freed by eina_stringshare_del() after use. + * * @param intent intent item to query. * @param key key to query in the dictionary. * * @return a newly allocated string or @c NULL in case of error or if the key does not exist. */ -EAPI char *ewk_intent_extra_get(const Ewk_Intent *intent, const char *key); +EAPI const char *ewk_intent_extra_get(const Ewk_Intent *intent, const char *key); /** * Retrieve a list of the names of extra metadata associated with the intent. * + * The item of a returned list should be freed by eina_stringshare_del() after use. + * * @param intent intent item to query. * * @return @c Eina_List with names of extra metadata on success, or @c NULL on failure, - * the Eina_List and its items should be freed after use. Use free() to free the - * items. + * the Eina_List and its items should be freed after use. Use eina_stringshare_del() + * to free the items. */ EAPI Eina_List *ewk_intent_extra_names_get(const Ewk_Intent *intent); diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_main.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_main.cpp new file mode 100644 index 000000000..0d01924bc --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_main.cpp @@ -0,0 +1,105 @@ +/* + Copyright (C) 2009-2010 ProFUSION embedded systems + Copyright (C) 2009-2011 Samsung Electronics + Copyright (C) 2012 Intel Corporation + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "ewk_main.h" + +#include <Ecore.h> +#include <Ecore_Evas.h> +#include <Edje.h> +#include <Eina.h> +#include <Evas.h> +#include <glib-object.h> +#include <glib.h> + +static int _ewkInitCount = 0; + +/** + * \var _ewk_log_dom + * @brief the log domain identifier that is used with EINA's macros + */ +int _ewk_log_dom = -1; + +int ewk_init(void) +{ + if (_ewkInitCount) + return ++_ewkInitCount; + + if (!eina_init()) + goto error_eina; + + _ewk_log_dom = eina_log_domain_register("ewebkit2", EINA_COLOR_ORANGE); + if (_ewk_log_dom < 0) { + EINA_LOG_CRIT("could not register log domain 'ewebkit2'"); + goto error_log_domain; + } + + if (!evas_init()) { + EINA_LOG_DOM_CRIT(_ewk_log_dom, "could not init evas."); + goto error_evas; + } + + if (!ecore_init()) { + EINA_LOG_DOM_CRIT(_ewk_log_dom, "could not init ecore."); + goto error_ecore; + } + + if (!ecore_evas_init()) { + EINA_LOG_DOM_CRIT(_ewk_log_dom, "could not init ecore_evas."); + goto error_ecore_evas; + } + + g_type_init(); + + if (!ecore_main_loop_glib_integrate()) { + EINA_LOG_DOM_WARN(_ewk_log_dom, "Ecore was not compiled with GLib support, some plugins will not " + "work (ie: Adobe Flash)"); + } + + return ++_ewkInitCount; + +error_ecore_evas: + ecore_shutdown(); +error_ecore: + evas_shutdown(); +error_evas: + eina_log_domain_unregister(_ewk_log_dom); + _ewk_log_dom = -1; +error_log_domain: + eina_shutdown(); +error_eina: + return 0; +} + +int ewk_shutdown(void) +{ + if (--_ewkInitCount) + return _ewkInitCount; + + ecore_evas_shutdown(); + ecore_shutdown(); + evas_shutdown(); + eina_log_domain_unregister(_ewk_log_dom); + _ewk_log_dom = -1; + eina_shutdown(); + + return 0; +} diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_main.h b/Source/WebKit2/UIProcess/API/efl/ewk_main.h new file mode 100644 index 000000000..28e93fe23 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_main.h @@ -0,0 +1,58 @@ +/* + Copyright (C) 2009-2010 ProFUSION embedded systems + Copyright (C) 2009-2010 Samsung Electronics + Copyright (C) 2012 Intel Corporation + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/** + * @file ewk_main.h + * @brief The general initialization of WebKit2-EFL, not tied to any view object. + */ + +#ifndef ewk_main_h +#define ewk_main_h + +#include <Eina.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initializes WebKit's instance. + * + * - initializes components needed by EFL, + * - increases a reference count of WebKit's instance. + * + * @return a reference count of WebKit's instance on success or 0 on failure + */ +EAPI int ewk_init(void); + +/** + * Decreases a reference count of WebKit's instance, possibly destroying it. + * + * If the reference count reaches 0 WebKit's instance is destroyed. + * + * @return a reference count of WebKit's instance + */ +EAPI int ewk_shutdown(void); + +#ifdef __cplusplus +} +#endif +#endif // ewk_main_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_url_response.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_url_response.cpp index 137753d60..8f9f5366a 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_url_response.cpp +++ b/Source/WebKit2/UIProcess/API/efl/ewk_url_response.cpp @@ -98,6 +98,13 @@ const char* ewk_url_response_mime_type_get(const Ewk_Url_Response* response) return response->mimeType; } +unsigned long ewk_url_response_content_length_get(const Ewk_Url_Response* response) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(response, 0); + + return response->coreResponse.expectedContentLength(); +} + /** * @internal * Constructs a Ewk_Url_Response from a WebCore::ResourceResponse. diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_url_response.h b/Source/WebKit2/UIProcess/API/efl/ewk_url_response.h index c02622dd7..35631ebef 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_url_response.h +++ b/Source/WebKit2/UIProcess/API/efl/ewk_url_response.h @@ -94,6 +94,17 @@ EAPI int ewk_url_response_status_code_get(const Ewk_Url_Response *response); */ EAPI const char *ewk_url_response_mime_type_get(const Ewk_Url_Response *response); +/** + * Get the expected content length of the #Ewk_Url_Response. + * + * It can be 0 if the server provided an incorrect or missing Content-Length. + * + * @param response a #Ewk_Url_Response. + * + * @return the expected content length of @a response or 0 in case of failure. + */ +EAPI unsigned long ewk_url_response_content_length_get(const Ewk_Url_Response *response); + #ifdef __cplusplus } #endif diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_url_scheme_request.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_url_scheme_request.cpp index 693ff3df6..32c3281f9 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_url_scheme_request.cpp +++ b/Source/WebKit2/UIProcess/API/efl/ewk_url_scheme_request.cpp @@ -115,7 +115,7 @@ uint64_t ewk_url_scheme_request_id_get(const Ewk_Url_Scheme_Request* request) return request->requestID; } -Eina_Bool ewk_url_scheme_request_finish(const Ewk_Url_Scheme_Request* request, void* contentData, unsigned int contentLength, const char* mimeType) +Eina_Bool ewk_url_scheme_request_finish(const Ewk_Url_Scheme_Request* request, const void* contentData, unsigned int contentLength, const char* mimeType) { EINA_SAFETY_ON_NULL_RETURN_VAL(request, false); diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_url_scheme_request.h b/Source/WebKit2/UIProcess/API/efl/ewk_url_scheme_request.h index 034cbd474..deaaf1892 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_url_scheme_request.h +++ b/Source/WebKit2/UIProcess/API/efl/ewk_url_scheme_request.h @@ -103,7 +103,7 @@ EAPI const char *ewk_url_scheme_request_path_get(const Ewk_Url_Scheme_Request *r * @param content_length the length of the @a content_data. * @param mime_type the content type of the stream or %c NULL if not known */ -EAPI Eina_Bool ewk_url_scheme_request_finish(const Ewk_Url_Scheme_Request *request, void *content_data, unsigned int content_length, const char *mime_type); +EAPI Eina_Bool ewk_url_scheme_request_finish(const Ewk_Url_Scheme_Request *request, const void *content_data, unsigned int content_length, const char *mime_type); #ifdef __cplusplus } diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp index 3f80aa11d..b1b1bcc08 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp +++ b/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp @@ -32,19 +32,31 @@ #include "ewk_context.h" #include "ewk_context_private.h" #include "ewk_intent_private.h" +#include "ewk_view_form_client_private.h" #include "ewk_view_loader_client_private.h" #include "ewk_view_policy_client_private.h" #include "ewk_view_private.h" #include "ewk_view_resource_load_client_private.h" #include "ewk_web_resource.h" +#include <Ecore_Evas.h> +#include <Edje.h> +#include <WebCore/Cursor.h> +#include <WebCore/EflScreenUtilities.h> #include <wtf/text/CString.h> +#if USE(ACCELERATED_COMPOSITING) +#include <Evas_GL.h> +#endif + using namespace WebKit; using namespace WebCore; static const char EWK_VIEW_TYPE_STR[] = "EWK2_View"; +static const int defaultCursorSize = 16; + typedef HashMap<uint64_t, Ewk_Web_Resource*> LoadingResourcesMap; +static void _ewk_view_priv_loading_resources_clear(LoadingResourcesMap& loadingResourcesMap); struct _Ewk_View_Private_Data { OwnPtr<PageClientImpl> pageClient; @@ -52,13 +64,35 @@ struct _Ewk_View_Private_Data { const char* title; const char* theme; const char* customEncoding; + const char* cursorGroup; + Evas_Object* cursorObject; LoadingResourcesMap loadingResourcesMap; +#ifdef HAVE_ECORE_X + bool isUsingEcoreX; +#endif + +#if USE(ACCELERATED_COMPOSITING) + Evas_GL* evasGl; + Evas_GL_Context* evasGlContext; + Evas_GL_Surface* evasGlSurface; +#endif + _Ewk_View_Private_Data() : uri(0) , title(0) , theme(0) , customEncoding(0) + , cursorGroup(0) + , cursorObject(0) +#ifdef HAVE_ECORE_X + , isUsingEcoreX(false) +#endif +#if USE(ACCELERATED_COMPOSITING) + , evasGl(0) + , evasGlContext(0) + , evasGlSurface(0) +#endif { } ~_Ewk_View_Private_Data() @@ -67,6 +101,10 @@ struct _Ewk_View_Private_Data { eina_stringshare_del(title); eina_stringshare_del(theme); eina_stringshare_del(customEncoding); + _ewk_view_priv_loading_resources_clear(loadingResourcesMap); + + if (cursorObject) + evas_object_del(cursorObject); } }; @@ -284,9 +322,24 @@ static Ewk_View_Private_Data* _ewk_view_priv_new(Ewk_View_Smart_Data* smartData) return 0; } +#ifdef HAVE_ECORE_X + priv->isUsingEcoreX = WebCore::isUsingEcoreX(smartData->base.evas); +#endif + return priv; } +static void _ewk_view_priv_loading_resources_clear(LoadingResourcesMap& loadingResourcesMap) +{ + // Clear the loadingResources HashMap. + LoadingResourcesMap::iterator it = loadingResourcesMap.begin(); + LoadingResourcesMap::iterator end = loadingResourcesMap.end(); + for ( ; it != end; ++it) + ewk_web_resource_unref(it->second); + + loadingResourcesMap.clear(); +} + static void _ewk_view_priv_del(Ewk_View_Private_Data* priv) { delete priv; @@ -309,9 +362,11 @@ static void _ewk_view_smart_add(Evas_Object* ewkView) } smartData->self = ewkView; - smartData->priv = _ewk_view_priv_new(smartData); smartData->api = api; + g_parentSmartClass.add(ewkView); + + smartData->priv = _ewk_view_priv_new(smartData); if (!smartData->priv) { EINA_LOG_CRIT("could not allocate _Ewk_View_Private_Data"); evas_object_smart_data_set(ewkView, 0); @@ -319,8 +374,6 @@ static void _ewk_view_smart_add(Evas_Object* ewkView) return; } - g_parentSmartClass.add(ewkView); - // Create evas_object_image to draw web contents. smartData->image = evas_object_image_add(smartData->base.evas); evas_object_image_alpha_set(smartData->image, false); @@ -369,6 +422,94 @@ static void _ewk_view_smart_move(Evas_Object* ewkView, Evas_Coord x, Evas_Coord _ewk_view_smart_changed(smartData); } +IntSize ewk_view_size_get(const Evas_Object* ewkView) +{ + int width, height; + evas_object_geometry_get(ewkView, 0, 0, &width, &height); + return IntSize(width, height); +} + +#if USE(ACCELERATED_COMPOSITING) +static bool ewk_view_create_gl_surface(const Evas_Object* ewkView, const IntSize& viewSize) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); + + Evas_GL_Config evasGlConfig = { + EVAS_GL_RGBA_8888, + EVAS_GL_DEPTH_BIT_8, + EVAS_GL_STENCIL_NONE, + EVAS_GL_OPTIONS_NONE, + EVAS_GL_MULTISAMPLE_NONE + }; + + ASSERT(!priv->evasGlSurface); + priv->evasGlSurface = evas_gl_surface_create(priv->evasGl, &evasGlConfig, viewSize.width(), viewSize.height()); + if (!priv->evasGlSurface) + return false; + + Evas_Native_Surface nativeSurface; + evas_gl_native_surface_get(priv->evasGl, priv->evasGlSurface, &nativeSurface); + evas_object_image_native_surface_set(smartData->image, &nativeSurface); + + return true; +} + +bool ewk_view_accelerated_compositing_mode_enter(const Evas_Object* ewkView) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); + + EINA_SAFETY_ON_NULL_RETURN_VAL(!priv->evasGl, false); + + Evas* evas = evas_object_evas_get(ewkView); + priv->evasGl = evas_gl_new(evas); + if (!priv->evasGl) + return false; + + priv->evasGlContext = evas_gl_context_create(priv->evasGl, 0); + if (!priv->evasGlContext) { + evas_gl_free(priv->evasGl); + priv->evasGl = 0; + return false; + } + + if (!ewk_view_create_gl_surface(ewkView, ewk_view_size_get(ewkView))) { + evas_gl_context_destroy(priv->evasGl, priv->evasGlContext); + priv->evasGlContext = 0; + + evas_gl_free(priv->evasGl); + priv->evasGl = 0; + return false; + } + + return true; +} + +bool ewk_view_accelerated_compositing_mode_exit(const Evas_Object* ewkView) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); + + EINA_SAFETY_ON_NULL_RETURN_VAL(priv->evasGl, false); + + if (priv->evasGlSurface) { + evas_gl_surface_destroy(priv->evasGl, priv->evasGlSurface); + priv->evasGlSurface = 0; + } + + if (priv->evasGlContext) { + evas_gl_context_destroy(priv->evasGl, priv->evasGlContext); + priv->evasGlContext = 0; + } + + evas_gl_free(priv->evasGl); + priv->evasGl = 0; + + return true; +} +#endif + static void _ewk_view_smart_calculate(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); @@ -382,6 +523,16 @@ static void _ewk_view_smart_calculate(Evas_Object* ewkView) if (smartData->changed.size) { if (priv->pageClient->page()->drawingArea()) priv->pageClient->page()->drawingArea()->setSize(IntSize(width, height), IntSize()); + +#if USE(ACCELERATED_COMPOSITING) + if (!priv->evasGlSurface) + return; + evas_gl_surface_destroy(priv->evasGl, priv->evasGlSurface); + priv->evasGlSurface = 0; + ewk_view_create_gl_surface(ewkView, IntSize(width, height)); + ewk_view_display(ewkView, IntRect(IntPoint(), IntSize(width, height))); +#endif + smartData->view.w = width; smartData->view.h = height; smartData->changed.size = false; @@ -510,9 +661,12 @@ Evas_Object* ewk_view_base_add(Evas* canvas, WKContextRef contextRef, WKPageGrou } priv->pageClient = PageClientImpl::create(toImpl(contextRef), toImpl(pageGroupRef), ewkView); - ewk_view_loader_client_attach(toAPI(priv->pageClient->page()), ewkView); - ewk_view_policy_client_attach(toAPI(priv->pageClient->page()), ewkView); - ewk_view_resource_load_client_attach(toAPI(priv->pageClient->page()), ewkView); + + WKPageRef wkPage = toAPI(priv->pageClient->page()); + ewk_view_form_client_attach(wkPage, ewkView); + ewk_view_loader_client_attach(wkPage, ewkView); + ewk_view_policy_client_attach(wkPage, ewkView); + ewk_view_resource_load_client_attach(wkPage, ewkView); ewk_view_theme_set(ewkView, DEFAULT_THEME_PATH"/default.edj"); @@ -529,15 +683,35 @@ Evas_Object* ewk_view_add(Evas* canvas) return ewk_view_add_with_context(canvas, ewk_context_default_get()); } -Eina_Bool ewk_view_uri_set(Evas_Object* ewkView, const char* uri) +/** + * @internal + * The uri of view was changed by the frame loader. + * + * Emits signal: "uri,changed" with pointer to new uri string. + */ +void ewk_view_uri_update(Evas_Object* ewkView) { - EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0); - EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0); + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); + + String activeURL = priv->pageClient->page()->activeURL(); + if (activeURL.isEmpty()) + return; + + if (!eina_stringshare_replace(&priv->uri, activeURL.utf8().data())) + return; - WKRetainPtr<WKURLRef> url(AdoptWK, WKURLCreateWithUTF8CString(uri)); - WKPageLoadURL(toAPI(priv->pageClient->page()), url.get()); + evas_object_smart_callback_call(ewkView, "uri,changed", static_cast<void*>(const_cast<char*>(priv->uri))); +} - eina_stringshare_replace(&priv->uri, uri); +Eina_Bool ewk_view_uri_set(Evas_Object* ewkView, const char* uri) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); + EINA_SAFETY_ON_NULL_RETURN_VAL(uri, false); + + priv->pageClient->page()->loadURL(uri); + ewk_view_uri_update(ewkView); return true; } @@ -555,7 +729,9 @@ Eina_Bool ewk_view_reload(Evas_Object* ewkView) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - WKPageReload(toAPI(priv->pageClient->page())); + priv->pageClient->page()->reload(/*reloadFromOrigin*/ false); + ewk_view_uri_update(ewkView); + return true; } @@ -564,7 +740,8 @@ Eina_Bool ewk_view_reload_bypass_cache(Evas_Object* ewkView) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - WKPageReloadFromOrigin(toAPI(priv->pageClient->page())); + priv->pageClient->page()->reload(/*reloadFromOrigin*/ true); + ewk_view_uri_update(ewkView); return true; } @@ -574,7 +751,8 @@ Eina_Bool ewk_view_stop(Evas_Object* ewkView) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - WKPageStopLoading(toAPI(priv->pageClient->page())); + priv->pageClient->page()->stopLoading(); + return true; } @@ -700,10 +878,27 @@ void ewk_view_title_changed(Evas_Object* ewkView, const char* title) double ewk_view_load_progress_get(const Evas_Object* ewkView) { - EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0); - EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0); + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, -1.0); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, -1.0); + + return priv->pageClient->page()->estimatedProgress(); +} + +Eina_Bool ewk_view_scale_set(Evas_Object* ewkView, double scaleFactor, int x, int y) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); + + priv->pageClient->page()->scalePage(scaleFactor, IntPoint(x, y)); + return true; +} + +double ewk_view_scale_get(const Evas_Object* ewkView) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, -1); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, -1); - return WKPageGetEstimatedProgress(toAPI(priv->pageClient->page())); + return priv->pageClient->page()->pageScaleFactor(); } Eina_Bool ewk_view_device_pixel_ratio_set(Evas_Object* ewkView, float ratio) @@ -712,13 +907,14 @@ Eina_Bool ewk_view_device_pixel_ratio_set(Evas_Object* ewkView, float ratio) EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); priv->pageClient->page()->setCustomDeviceScaleFactor(ratio); + return true; } float ewk_view_device_pixel_ratio_get(const Evas_Object* ewkView) { - EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 1); - EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 1); + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, -1.0); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, -1.0); return priv->pageClient->page()->deviceScaleFactor(); } @@ -762,9 +958,62 @@ const char* ewk_view_theme_get(const Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0); + return priv->theme; } +void ewk_view_cursor_set(Evas_Object* ewkView, const Cursor& cursor) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); + + const char* group = cursor.platformCursor(); + if (!group || group == priv->cursorGroup) + return; + + priv->cursorGroup = group; + + if (priv->cursorObject) + evas_object_del(priv->cursorObject); + priv->cursorObject = edje_object_add(smartData->base.evas); + + Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(smartData->base.evas); + if (!priv->theme || !edje_object_file_set(priv->cursorObject, priv->theme, group)) { + evas_object_del(priv->cursorObject); + priv->cursorObject = 0; + + ecore_evas_object_cursor_set(ecoreEvas, 0, 0, 0, 0); +#ifdef HAVE_ECORE_X + if (priv->isUsingEcoreX) + WebCore::applyFallbackCursor(ecoreEvas, group); +#endif + return; + } + + Evas_Coord width, height; + edje_object_size_min_get(priv->cursorObject, &width, &height); + if (width <= 0 || height <= 0) + edje_object_size_min_calc(priv->cursorObject, &width, &height); + if (width <= 0 || height <= 0) { + width = defaultCursorSize; + height = defaultCursorSize; + } + evas_object_resize(priv->cursorObject, width, height); + + const char* data; + int hotspotX = 0; + data = edje_object_data_get(priv->cursorObject, "hot.x"); + if (data) + hotspotX = atoi(data); + + int hotspotY = 0; + data = edje_object_data_get(priv->cursorObject, "hot.y"); + if (data) + hotspotY = atoi(data); + + ecore_evas_object_cursor_set(ecoreEvas, priv->cursorObject, EVAS_LAYER_MAX, hotspotX, hotspotY); +} + void ewk_view_display(Evas_Object* ewkView, const IntRect& rect) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); @@ -774,16 +1023,62 @@ void ewk_view_display(Evas_Object* ewkView, const IntRect& rect) evas_object_image_data_update_add(smartData->image, rect.x(), rect.y(), rect.width(), rect.height()); } +/** + * @internal + * A download for that view was cancelled. + * + * Emits signal: "download,cancelled" with pointer to a Ewk_Download_Job. + */ +void ewk_view_download_job_cancelled(Evas_Object* ewkView, Ewk_Download_Job* download) +{ + evas_object_smart_callback_call(ewkView, "download,cancelled", download); +} + +/** + * @internal + * A new download has been requested for that view. + * + * Emits signal: "download,request" with pointer to a Ewk_Download_Job. + */ +void ewk_view_download_job_requested(Evas_Object* ewkView, Ewk_Download_Job* download) +{ + evas_object_smart_callback_call(ewkView, "download,request", download); +} + +/** + * @internal + * A download for that view has failed. + * + * Emits signal: "download,failed" with pointer to a Ewk_Download_Job_Error. + */ +void ewk_view_download_job_failed(Evas_Object* ewkView, Ewk_Download_Job* download, Ewk_Web_Error* error) +{ + Ewk_Download_Job_Error downloadError = { download, error }; + evas_object_smart_callback_call(ewkView, "download,failed", &downloadError); +} + +/** + * @internal + * A download for that view finished successfully. + * + * Emits signal: "download,finished" with pointer to a Ewk_Download_Job. + */ +void ewk_view_download_job_finished(Evas_Object* ewkView, Ewk_Download_Job* download) +{ + evas_object_smart_callback_call(ewkView, "download,finished", download); +} + Eina_Bool ewk_view_back(Evas_Object* ewkView) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - WKPageRef pageRef = toAPI(priv->pageClient->page()); - if (WKPageCanGoBack(pageRef)) { - WKPageGoBack(pageRef); + WebPageProxy* page = priv->pageClient->page(); + if (page->canGoBack()) { + page->goBack(); return true; } + return false; } @@ -792,11 +1087,12 @@ Eina_Bool ewk_view_forward(Evas_Object* ewkView) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - WKPageRef pageRef = toAPI(priv->pageClient->page()); - if (WKPageCanGoForward(pageRef)) { - WKPageGoForward(pageRef); + WebPageProxy* page = priv->pageClient->page(); + if (page->canGoForward()) { + page->goForward(); return true; } + return false; } @@ -807,8 +1103,9 @@ Eina_Bool ewk_view_intent_deliver(Evas_Object* ewkView, Ewk_Intent* intent) EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); EINA_SAFETY_ON_NULL_RETURN_VAL(intent, false); - WKPageRef wkPage = toAPI(priv->pageClient->page()); - WKPageDeliverIntentToFrame(wkPage, WKPageGetMainFrame(wkPage), ewk_intent_WKIntentDataRef_get(intent)); + WebPageProxy* page = priv->pageClient->page(); + page->deliverIntentToFrame(page->mainFrame(), toImpl(ewk_intent_WKIntentDataRef_get(intent))); + return true; #else return false; @@ -820,7 +1117,7 @@ Eina_Bool ewk_view_back_possible(Evas_Object* ewkView) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - return WKPageCanGoBack(toAPI(priv->pageClient->page())); + return priv->pageClient->page()->canGoBack(); } Eina_Bool ewk_view_forward_possible(Evas_Object* ewkView) @@ -828,7 +1125,7 @@ Eina_Bool ewk_view_forward_possible(Evas_Object* ewkView) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - return WKPageCanGoForward(toAPI(priv->pageClient->page())); + return priv->pageClient->page()->canGoForward(); } void ewk_view_image_data_set(Evas_Object* ewkView, void* imageData, const IntSize& size) @@ -844,6 +1141,17 @@ void ewk_view_image_data_set(Evas_Object* ewkView, void* imageData, const IntSiz /** * @internal + * Reports that a form request is about to be submitted. + * + * Emits signal: "form,submission,request" with pointer to Ewk_Form_Submission_Request. + */ +void ewk_view_form_submission_request_new(Evas_Object* ewkView, Ewk_Form_Submission_Request* request) +{ + evas_object_smart_callback_call(ewkView, "form,submission,request", request); +} + +/** + * @internal * Reports load failed with error information. * * Emits signal: "load,error" with pointer to Ewk_Web_Error. @@ -861,6 +1169,7 @@ void ewk_view_load_error(Evas_Object* ewkView, const Ewk_Web_Error* error) */ void ewk_view_load_finished(Evas_Object* ewkView) { + ewk_view_uri_update(ewkView); evas_object_smart_callback_call(ewkView, "load,finished", 0); } @@ -883,6 +1192,7 @@ void ewk_view_load_provisional_failed(Evas_Object* ewkView, const Ewk_Web_Error* */ void ewk_view_load_provisional_redirect(Evas_Object* ewkView) { + ewk_view_uri_update(ewkView); evas_object_smart_callback_call(ewkView, "load,provisional,redirect", 0); } @@ -899,12 +1209,9 @@ void ewk_view_load_provisional_started(Evas_Object* ewkView) // The main frame started provisional load, we should clear // the loadingResources HashMap to start clean. - LoadingResourcesMap::iterator it = priv->loadingResourcesMap.begin(); - LoadingResourcesMap::iterator end = priv->loadingResourcesMap.end(); - for ( ; it != end; ++it) - ewk_web_resource_unref(it->second); - priv->loadingResourcesMap.clear(); + _ewk_view_priv_loading_resources_clear(priv->loadingResourcesMap); + ewk_view_uri_update(ewkView); evas_object_smart_callback_call(ewkView, "load,provisional,started", 0); } @@ -940,6 +1247,7 @@ Eina_Bool ewk_view_html_string_load(Evas_Object* ewkView, const char* html, cons priv->pageClient->page()->loadAlternateHTMLString(String::fromUTF8(html), baseUrl ? String::fromUTF8(baseUrl) : "", String::fromUTF8(unreachableUrl)); else priv->pageClient->page()->loadHTMLString(String::fromUTF8(html), baseUrl ? String::fromUTF8(baseUrl) : ""); + ewk_view_uri_update(ewkView); return true; } @@ -970,11 +1278,12 @@ const char* ewk_view_setting_encoding_custom_get(const Evas_Object* ewkView) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0); - WKRetainPtr<WKStringRef> wkEncodingName(AdoptWK, WKPageCopyCustomTextEncodingName(toAPI(priv->pageClient->page()))); - if (WKStringIsEmpty(wkEncodingName.get())) + String customEncoding = priv->pageClient->page()->customTextEncodingName(); + if (customEncoding.isEmpty()) return 0; - eina_stringshare_replace(&priv->customEncoding, toImpl(wkEncodingName.get())->string().utf8().data()); + eina_stringshare_replace(&priv->customEncoding, customEncoding.utf8().data()); + return priv->customEncoding; } @@ -983,8 +1292,8 @@ Eina_Bool ewk_view_setting_encoding_custom_set(Evas_Object* ewkView, const char* EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - WKRetainPtr<WKStringRef> wkEncodingName = encoding ? adoptWK(WKStringCreateWithUTF8CString(encoding)) : 0; if (eina_stringshare_replace(&priv->customEncoding, encoding)) - WKPageSetCustomTextEncodingName(toAPI(priv->pageClient->page()), wkEncodingName.get()); + priv->pageClient->page()->setCustomTextEncodingName(encoding ? encoding : String()); + return true; } diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_view.h b/Source/WebKit2/UIProcess/API/efl/ewk_view.h index 924dbcf67..057f725bd 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_view.h +++ b/Source/WebKit2/UIProcess/API/efl/ewk_view.h @@ -26,6 +26,20 @@ * * The following signals (see evas_object_smart_callback_add()) are emitted: * + * - "download,cancelled", Ewk_Download_Job*: reports that a download was effectively cancelled. + * - "download,failed", Ewk_Download_Job_Error*: reports that a download failed with the given error. + * - "download,finished", Ewk_Download_Job*: reports that a download completed successfully. + * - "download,request", Ewk_Download_Job*: reports that a new download has been requested. The client should set the + * destination path by calling ewk_download_job_destination_set() or the download will fail. + * - "form,submission,request", Ewk_Form_Submission_Request*: Reports that a form request is about to be submitted. + * The Ewk_Form_Submission_Request passed contains information about the text fields of the form. This + * is typically used to store login information that can be used later to pre-fill the form. + * The form will not be submitted until ewk_form_submission_request_submit() is called. + * It is possible to handle the form submission request asynchronously, by simply calling + * ewk_form_submission_request_ref() on the request and calling ewk_form_submission_request_submit() + * when done to continue with the form submission. If the last reference is removed on a + * #Ewk_Form_Submission_Request and the form has not been submitted yet, + * ewk_form_submission_request_submit() will be called automatically. * - "intent,request,new", Ewk_Intent_Request*: reports new Web intent request. * - "intent,service,register", Ewk_Intent_Service*: reports new Web intent service registration. * - "load,error", const Ewk_Web_Error*: reports main frame load failed. @@ -46,12 +60,14 @@ * - "resource,request,response", Ewk_Web_Resource_Load_Response*: a response to a resource request was received. * - "resource,request,sent", const Ewk_Web_Resource_Request*: a resource request was sent. * - "title,changed", const char*: title of the main frame was changed. + * - "uri,changed", const char*: uri of the main frame was changed. */ #ifndef ewk_view_h #define ewk_view_h #include "ewk_context.h" +#include "ewk_download_job.h" #include "ewk_intent.h" #include "ewk_url_request.h" #include "ewk_url_response.h" @@ -188,6 +204,17 @@ struct _Ewk_Web_Resource_Load_Error { Ewk_Web_Error *error; /**< load error */ }; +/// Creates a type name for _Ewk_Download_Job_Error. +typedef struct _Ewk_Download_Job_Error Ewk_Download_Job_Error; + +/** + * @brief Structure containing details about a download failure. + */ +struct _Ewk_Download_Job_Error { + Ewk_Download_Job *download_job; /**< download that failed */ + Ewk_Web_Error *error; /**< download error */ +}; + /** * Creates a new EFL WebKit view object. * @@ -213,7 +240,8 @@ EAPI Evas_Object *ewk_view_add_with_context(Evas *e, Ewk_Context *context); * @param o view object to load @a URI * @param uri uniform resource identifier to load * - * @return @c EINA_TRUE is returned if @a o is valid, irrespective of load. + * @return @c EINA_TRUE is returned if @a o is valid, irrespective of load, + * or @c EINA_FALSE on failure */ EAPI Eina_Bool ewk_view_uri_set(Evas_Object *o, const char *uri); @@ -326,7 +354,8 @@ EAPI const char *ewk_view_title_get(const Evas_Object *o); * * @param o view object to get the current progress * - * @return the load progres of page, value from 0.0 to 1.0. + * @return the load progress of page, value from 0.0 to 1.0, + * or @c -1.0 on failure */ EAPI double ewk_view_load_progress_get(const Evas_Object *o); @@ -350,6 +379,30 @@ EAPI double ewk_view_load_progress_get(const Evas_Object *o); EAPI Eina_Bool ewk_view_html_string_load(Evas_Object *o, const char *html, const char *baseUrl, const char *unreachableUrl); /** + * Scales the current page, centered at the given point. + * + * @param o view object to set the zoom level + * @param scale_factor a new level to set + * @param cx x of center coordinate + * @param cy y of center coordinate + * + * @return @c EINA_TRUE on success or @c EINA_FALSE otherwise + */ +Eina_Bool ewk_view_scale_set(Evas_Object *o, double scaleFactor, int x, int y); + +/** + * Queries the current scale factor of the page. + * + * It returns previous scale factor after ewk_view_scale_set is called immediately + * until scale factor of page is really changed. + * + * @param o view object to get the scale factor + * + * @return current scale factor in use on success or @c -1.0 on failure + */ +double ewk_view_scale_get(const Evas_Object *o); + +/** * Queries the ratio between the CSS units and device pixels when the content is unscaled. * * When designing touch-friendly contents, knowing the approximated target size on a device @@ -382,7 +435,8 @@ EAPI Eina_Bool ewk_view_html_string_load(Evas_Object *o, const char *html, const * * @param o view object to get device pixel ratio * - * @return the ratio between the CSS units and device pixels. + * @return the ratio between the CSS units and device pixels, + * or @c -1.0 on failure */ EAPI float ewk_view_device_pixel_ratio_get(const Evas_Object *o); diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_view_form_client.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_view_form_client.cpp new file mode 100644 index 000000000..264ac5e47 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_view_form_client.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "WKPage.h" +#include "ewk_form_submission_request.h" +#include "ewk_form_submission_request_private.h" +#include "ewk_view_form_client_private.h" +#include "ewk_view_private.h" + +static void willSubmitForm(WKPageRef page, WKFrameRef frame, WKFrameRef sourceFrame, WKDictionaryRef values, WKTypeRef userData, WKFormSubmissionListenerRef listener, const void* clientInfo) +{ + Evas_Object* ewkView = static_cast<Evas_Object*>(const_cast<void*>(clientInfo)); + + Ewk_Form_Submission_Request* request = ewk_form_submission_request_new(values, listener); + ewk_view_form_submission_request_new(ewkView, request); + ewk_form_submission_request_unref(request); +} + +void ewk_view_form_client_attach(WKPageRef pageRef, Evas_Object* ewkView) +{ + WKPageFormClient formClient; + memset(&formClient, 0, sizeof(WKPageFormClient)); + formClient.version = kWKPageFormClientCurrentVersion; + formClient.clientInfo = ewkView; + formClient.willSubmitForm = willSubmitForm; + WKPageSetPageFormClient(pageRef, &formClient); +} diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_view_form_client_private.h b/Source/WebKit2/UIProcess/API/efl/ewk_view_form_client_private.h new file mode 100644 index 000000000..9feb4a138 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_view_form_client_private.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ewk_view_form_client_private_h +#define ewk_view_form_client_private_h + +#include <Evas.h> +#include <WebKit2/WKBase.h> + +void ewk_view_form_client_attach(WKPageRef pageRef, Evas_Object* ewkView); + +#endif // ewk_view_form_client_private_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_view_private.h b/Source/WebKit2/UIProcess/API/efl/ewk_view_private.h index 3c9ce94a7..3b57a7618 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_view_private.h +++ b/Source/WebKit2/UIProcess/API/efl/ewk_view_private.h @@ -26,10 +26,13 @@ #include <WebKit2/WKBase.h> namespace WebCore { +class Cursor; class IntRect; class IntSize; } +typedef struct _Ewk_Download_Job Ewk_Download_Job; +typedef struct _Ewk_Form_Submission_Request Ewk_Form_Submission_Request; typedef struct _Ewk_Url_Request Ewk_Url_Request; typedef struct _Ewk_Url_Response Ewk_Url_Response; typedef struct _Ewk_Web_Error Ewk_Web_Error; @@ -42,7 +45,13 @@ typedef struct _Ewk_Intent Ewk_Intent; typedef struct _Ewk_Intent_Service Ewk_Intent_Service; #endif +void ewk_view_cursor_set(Evas_Object* ewkView, const WebCore::Cursor& cursor); void ewk_view_display(Evas_Object* ewkView, const WebCore::IntRect& rect); +void ewk_view_download_job_cancelled(Evas_Object* ewkView, Ewk_Download_Job*); +void ewk_view_download_job_failed(Evas_Object* ewkView, Ewk_Download_Job*, Ewk_Web_Error*); +void ewk_view_download_job_finished(Evas_Object* ewkView, Ewk_Download_Job*); +void ewk_view_download_job_requested(Evas_Object* ewkView, Ewk_Download_Job*); +void ewk_view_form_submission_request_new(Evas_Object* ewkView, Ewk_Form_Submission_Request*); void ewk_view_image_data_set(Evas_Object* ewkView, void* imageData, const WebCore::IntSize& size); void ewk_view_load_error(Evas_Object* ewkView, const Ewk_Web_Error* error); void ewk_view_load_finished(Evas_Object* ewkView); @@ -69,5 +78,11 @@ void ewk_view_intent_service_register(Evas_Object* ewkView, const Ewk_Intent_Ser #endif WebKit::WebPageProxy* ewk_view_page_get(const Evas_Object* ewkView); +WebCore::IntSize ewk_view_size_get(const Evas_Object* ewkView); + +#if USE(ACCELERATED_COMPOSITING) +bool ewk_view_accelerated_compositing_mode_enter(const Evas_Object* ewkView); +bool ewk_view_accelerated_compositing_mode_exit(const Evas_Object* ewkView); +#endif #endif // ewk_view_private_h diff --git a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.cpp b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.cpp index b8da86dce..4069e25fa 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.cpp +++ b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.cpp @@ -47,12 +47,7 @@ EWK2UnitTestBase::EWK2UnitTestBase() void EWK2UnitTestBase::SetUp() { - ASSERT_GT(ecore_evas_init(), 0); - - // glib support (for libsoup). - g_type_init(); - if (!ecore_main_loop_glib_integrate()) - fprintf(stderr, "WARNING: Glib main loop integration is not working. Some tests may fail."); + ewk_init(); unsigned int width = environment->defaultWidth(); unsigned int height = environment->defaultHeight(); @@ -77,7 +72,7 @@ void EWK2UnitTestBase::TearDown() { evas_object_del(m_webView); ecore_evas_free(m_ecoreEvas); - ecore_evas_shutdown(); + ewk_shutdown(); } void EWK2UnitTestBase::loadUrlSync(const char* url) @@ -93,4 +88,28 @@ void EWK2UnitTestBase::loadUrlSync(const char* url) evas_object_smart_callback_del(m_webView, "load,finished", onLoadFinished); } +struct TitleChangedData { + CString expectedTitle; + bool done; +}; + +static void onTitleChanged(void* userData, Evas_Object* webView, void* eventInfo) +{ + TitleChangedData* data = static_cast<TitleChangedData*>(userData); + + if (!strcmp(ewk_view_title_get(webView), data->expectedTitle.data())) + data->done = true; +} + +void EWK2UnitTestBase::waitUntilTitleChangedTo(const char* expectedTitle) +{ + TitleChangedData data = { expectedTitle, false }; + evas_object_smart_callback_add(m_webView, "title,changed", onTitleChanged, &data); + + while (!data.done) + ecore_main_loop_iterate(); + + evas_object_smart_callback_del(m_webView, "title,changed", onTitleChanged); +} + } // namespace EWK2UnitTest diff --git a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.h b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.h index 8fa1b5021..64b9bce60 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.h +++ b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.h @@ -37,6 +37,7 @@ protected: virtual void TearDown(); void loadUrlSync(const char* url); + void waitUntilTitleChangedTo(const char* expectedTitle); private: Evas_Object* m_webView; diff --git a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp index e7bc0d621..fae77242f 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp +++ b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp @@ -20,6 +20,8 @@ #include "config.h" #include "EWK2UnitTestEnvironment.h" +#include <wtf/text/StringConcatenate.h> + namespace EWK2UnitTest { EWK2UnitTestEnvironment::EWK2UnitTestEnvironment(bool useX11Window) @@ -39,4 +41,9 @@ const char* EWK2UnitTestEnvironment::defaultTheme() const return TEST_THEME_DIR"/default.edj"; } +CString EWK2UnitTestEnvironment::urlForResource(const char* resource) +{ + return makeString("file://"TEST_RESOURCES_DIR"/", resource).utf8(); +} + } // namespace EWK2UnitTest diff --git a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.h b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.h index fac0f5988..d010b6237 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.h +++ b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.h @@ -19,7 +19,9 @@ #ifndef EWK2UnitTestEnvironment_h #define EWK2UnitTestEnvironment_h +#include <Eina.h> #include <gtest/gtest.h> +#include <wtf/text/CString.h> namespace EWK2UnitTest { @@ -30,6 +32,7 @@ public: bool useX11Window() const { return m_useX11Window; } const char* defaultTestPageUrl() const; const char* defaultTheme() const; + CString urlForResource(const char* resource); virtual unsigned int defaultWidth() const { return m_defaultWidth; } virtual unsigned int defaultHeight() const { return m_defaultHeight; } diff --git a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestServer.cpp b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestServer.cpp index 13e577984..52e6af46e 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestServer.cpp +++ b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestServer.cpp @@ -26,7 +26,7 @@ EWK2UnitTestServer::EWK2UnitTestServer() SoupAddress* address = soup_address_new("127.0.0.1", SOUP_ADDRESS_ANY_PORT); soup_address_resolve_sync(address, 0); - m_soupServer = soup_server_new(SOUP_SERVER_INTERFACE, address, 0); + m_soupServer = soup_server_new(SOUP_SERVER_INTERFACE, address, static_cast<char*>(0)); m_baseURI = soup_uri_new("http://127.0.0.1/"); soup_uri_set_port(m_baseURI, soup_server_get_port(m_soupServer)); g_object_unref(address); diff --git a/Source/WebKit2/UIProcess/API/efl/tests/resources/redirect_uri_to_default.html b/Source/WebKit2/UIProcess/API/efl/tests/resources/redirect_uri_to_default.html new file mode 100644 index 000000000..846fd1113 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/tests/resources/redirect_uri_to_default.html @@ -0,0 +1,6 @@ +<!doctype html> +<body> +<script> +location.href="./default_test_page.html"; +</script> +</body> diff --git a/Source/WebKit2/UIProcess/API/efl/tests/resources/test.pdf b/Source/WebKit2/UIProcess/API/efl/tests/resources/test.pdf Binary files differnew file mode 100644 index 000000000..2424c19d9 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/tests/resources/test.pdf diff --git a/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_context.cpp b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_context.cpp new file mode 100644 index 000000000..034f87140 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_context.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "UnitTestUtils/EWK2UnitTestBase.h" +#include "UnitTestUtils/EWK2UnitTestEnvironment.h" +#include <EWebKit2.h> +#include <gtest/gtest.h> + +using namespace EWK2UnitTest; + +extern EWK2UnitTestEnvironment* environment; + +static const char htmlReply[] = "<html><head><title>Foo</title></head><body>Bar</body></html>"; + +TEST_F(EWK2UnitTestBase, ewk_context_default_get) +{ + Ewk_Context* defaultContext = ewk_context_default_get(); + ASSERT_TRUE(defaultContext); + ASSERT_EQ(defaultContext, ewk_context_default_get()); +} + +TEST_F(EWK2UnitTestBase, ewk_context_cookie_manager_get) +{ + Ewk_Cookie_Manager* cookieManager = ewk_context_cookie_manager_get(ewk_context_default_get()); + ASSERT_TRUE(cookieManager); + ASSERT_EQ(cookieManager, ewk_context_cookie_manager_get(ewk_context_default_get())); +} + +static void schemeRequestCallback(Ewk_Url_Scheme_Request* request, void* userData) +{ + const char* scheme = ewk_url_scheme_request_scheme_get(request); + ASSERT_STREQ(scheme, "fooscheme"); + const char* url = ewk_url_scheme_request_url_get(request); + ASSERT_STREQ(url, "fooscheme:MyPath"); + const char* path = ewk_url_scheme_request_path_get(request); + ASSERT_STREQ(path, "MyPath"); + ASSERT_TRUE(ewk_url_scheme_request_finish(request, htmlReply, strlen(htmlReply), "text/html")); +} + +TEST_F(EWK2UnitTestBase, ewk_context_uri_scheme_register) +{ + ewk_context_uri_scheme_register(ewk_context_default_get(), "fooscheme", schemeRequestCallback, 0); + loadUrlSync("fooscheme:MyPath"); + ASSERT_STREQ(ewk_view_title_get(webView()), "Foo"); +} diff --git a/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_cookie_manager.cpp b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_cookie_manager.cpp index 86815b42c..7dbd496bd 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_cookie_manager.cpp +++ b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_cookie_manager.cpp @@ -153,6 +153,75 @@ TEST_F(EWK2UnitTestBase, ewk_cookie_manager_accept_policy) ASSERT_EQ(countHostnamesWithCookies(cookieManager), 0); } +void onCookiesChanged(void *eventInfo) +{ + bool* cookiesChanged = static_cast<bool*>(eventInfo); + *cookiesChanged = true; +} + +TEST_F(EWK2UnitTestBase, ewk_cookie_manager_changes_watch) +{ + OwnPtr<EWK2UnitTestServer> httpServer = adoptPtr(new EWK2UnitTestServer); + httpServer->run(serverCallback); + + Ewk_Cookie_Manager* cookieManager = ewk_context_cookie_manager_get(ewk_context_default_get()); + ASSERT_TRUE(cookieManager); + + ewk_cookie_manager_accept_policy_set(cookieManager, EWK_COOKIE_ACCEPT_POLICY_ALWAYS); + ASSERT_EQ(getAcceptPolicy(cookieManager), EWK_COOKIE_ACCEPT_POLICY_ALWAYS); + + // Watch for changes + bool cookiesChanged = false; + ewk_cookie_manager_changes_watch(cookieManager, onCookiesChanged, &cookiesChanged); + + // Check for cookie changes notifications + loadUrlSync(httpServer->getURIForPath("/index.html").data()); + + while (!cookiesChanged) + ecore_main_loop_iterate(); + ASSERT_TRUE(cookiesChanged); + + cookiesChanged = false; + ewk_cookie_manager_cookies_clear(cookieManager); + while (!cookiesChanged) + ecore_main_loop_iterate(); + ASSERT_TRUE(cookiesChanged); + + // Stop watching for notifications + ewk_cookie_manager_changes_watch(cookieManager, 0, 0); + cookiesChanged = false; + loadUrlSync(httpServer->getURIForPath("/index.html").data()); + ASSERT_EQ(countHostnamesWithCookies(cookieManager), 2); + ASSERT_FALSE(cookiesChanged); + + // Watch again for notifications + ewk_cookie_manager_changes_watch(cookieManager, onCookiesChanged, &cookiesChanged); + + // Make sure we don't get notifications when loading setting an existing persistent storage + char textStorage1[] = "/tmp/txt-cookie.XXXXXX"; + ASSERT_TRUE(mktemp(textStorage1)); + char textStorage2[] = "/tmp/txt-cookie.XXXXXX"; + ASSERT_TRUE(mktemp(textStorage2)); + + ewk_cookie_manager_persistent_storage_set(cookieManager, textStorage1, EWK_COOKIE_PERSISTENT_STORAGE_TEXT); + loadUrlSync(httpServer->getURIForPath("/index.html").data()); + ASSERT_EQ(countHostnamesWithCookies(cookieManager), 2); + + cookiesChanged = false; + ewk_cookie_manager_persistent_storage_set(cookieManager, textStorage2, EWK_COOKIE_PERSISTENT_STORAGE_TEXT); + ASSERT_EQ(countHostnamesWithCookies(cookieManager), 0); + + ewk_cookie_manager_persistent_storage_set(cookieManager, textStorage1, EWK_COOKIE_PERSISTENT_STORAGE_TEXT); + ASSERT_EQ(countHostnamesWithCookies(cookieManager), 2); + + ASSERT_FALSE(cookiesChanged); + + // Final clean up. + ewk_cookie_manager_changes_watch(cookieManager, 0, 0); + unlink(textStorage1); + unlink(textStorage2); +} + TEST_F(EWK2UnitTestBase, ewk_cookie_manager_cookies_delete) { OwnPtr<EWK2UnitTestServer> httpServer = adoptPtr(new EWK2UnitTestServer); diff --git a/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_download_job.cpp b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_download_job.cpp new file mode 100644 index 000000000..22c97aad8 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_download_job.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "UnitTestUtils/EWK2UnitTestBase.h" +#include "UnitTestUtils/EWK2UnitTestEnvironment.h" +#include "UnitTestUtils/EWK2UnitTestServer.h" +#include <EWebKit2.h> +#include <Ecore.h> +#include <gtest/gtest.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> + +using namespace EWK2UnitTest; +using namespace WTF; + +extern EWK2UnitTestEnvironment* environment; + +static const char serverSuggestedFilename[] = "webkit-downloaded-file"; +static const char testFilePath[] = "/test.pdf"; + +struct DownloadTestData { + const char* fileUrl; + const char* destinationPath; +}; + +static inline bool fileExists(const char* path) +{ + struct stat buf; + return !stat(path, &buf); +} + +static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, void*) +{ + if (message->method != SOUP_METHOD_GET) { + soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + Eina_Strbuf* filePath = eina_strbuf_new(); + eina_strbuf_append(filePath, TEST_RESOURCES_DIR); + eina_strbuf_append(filePath, path); + + Eina_File* f = eina_file_open(eina_strbuf_string_get(filePath), false); + eina_strbuf_free(filePath); + if (!f) { + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); + soup_message_body_complete(message->response_body); + return; + } + + size_t fileSize = eina_file_size_get(f); + + void* contents = eina_file_map_all(f, EINA_FILE_POPULATE); + if (!contents) { + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); + soup_message_body_complete(message->response_body); + return; + } + + soup_message_set_status(message, SOUP_STATUS_OK); + + Eina_Strbuf* contentDisposition = eina_strbuf_new(); + eina_strbuf_append_printf(contentDisposition, "filename=%s", serverSuggestedFilename); + soup_message_headers_append(message->response_headers, "Content-Disposition", eina_strbuf_string_get(contentDisposition)); + eina_strbuf_free(contentDisposition); + + soup_message_body_append(message->response_body, SOUP_MEMORY_COPY, contents, fileSize); + soup_message_body_complete(message->response_body); + + eina_file_map_free(f, contents); + eina_file_close(f); +} + +static void on_download_requested(void* userData, Evas_Object* webview, void* eventInfo) +{ + DownloadTestData* testData = static_cast<DownloadTestData*>(userData); + Ewk_Download_Job* download = static_cast<Ewk_Download_Job*>(eventInfo); + ASSERT_EQ(ewk_download_job_state_get(download), EWK_DOWNLOAD_JOB_STATE_NOT_STARTED); + ASSERT_EQ(ewk_download_job_estimated_progress_get(download), 0); + ASSERT_EQ(ewk_download_job_elapsed_time_get(download), 0); + + Ewk_Url_Request* request = ewk_download_job_request_get(download); + ASSERT_TRUE(request); + EXPECT_STREQ(ewk_url_request_url_get(request), testData->fileUrl); + + Ewk_Url_Response* response = ewk_download_job_response_get(download); + ASSERT_TRUE(response); + EXPECT_STREQ(ewk_url_response_mime_type_get(response), "application/pdf"); + + EXPECT_STREQ(ewk_download_job_suggested_filename_get(download), serverSuggestedFilename); + + ASSERT_FALSE(fileExists(testData->destinationPath)); + ewk_download_job_destination_set(download, testData->destinationPath); + EXPECT_STREQ(ewk_download_job_destination_get(download), testData->destinationPath); +} + +static void on_download_cancelled(void* userData, Evas_Object* webview, void* eventInfo) +{ + fprintf(stderr, "Download was cancelled.\n"); + ecore_main_loop_quit(); + FAIL(); +} + +static void on_download_failed(void* userData, Evas_Object* webview, void* eventInfo) +{ + Ewk_Download_Job_Error* downloadError = static_cast<Ewk_Download_Job_Error*>(eventInfo); + fprintf(stderr, "Download error: %s\n", ewk_web_error_description_get(downloadError->error)); + ecore_main_loop_quit(); + FAIL(); +} + +static void on_download_finished(void* userData, Evas_Object* webview, void* eventInfo) +{ + DownloadTestData* testData = static_cast<DownloadTestData*>(userData); + Ewk_Download_Job* download = static_cast<Ewk_Download_Job*>(eventInfo); + + ASSERT_EQ(ewk_download_job_estimated_progress_get(download), 1); + ASSERT_EQ(ewk_download_job_state_get(download), EWK_DOWNLOAD_JOB_STATE_FINISHED); + ASSERT_GT(ewk_download_job_elapsed_time_get(download), 0); + + ASSERT_TRUE(fileExists(testData->destinationPath)); + + ecore_main_loop_quit(); +} + +TEST_F(EWK2UnitTestBase, ewk_download) +{ + OwnPtr<EWK2UnitTestServer> httpServer = adoptPtr(new EWK2UnitTestServer); + httpServer->run(serverCallback); + + // Generate unique name for destination file. + char destinationPath[] = "/tmp/pdf-file.XXXXXX"; + ASSERT_TRUE(mktemp(destinationPath)); + + CString fileUrl = httpServer->getURIForPath(testFilePath); + + DownloadTestData userData = { fileUrl.data(), destinationPath }; + ASSERT_FALSE(fileExists(destinationPath)); + + evas_object_smart_callback_add(webView(), "download,request", on_download_requested, &userData); + evas_object_smart_callback_add(webView(), "download,cancel", on_download_cancelled, &userData); + evas_object_smart_callback_add(webView(), "download,failed", on_download_failed, &userData); + evas_object_smart_callback_add(webView(), "download,finished", on_download_finished, &userData); + + // Download test pdf + ewk_view_uri_set(webView(), fileUrl.data()); + ecore_main_loop_begin(); + + // Clean up + unlink(destinationPath); +} diff --git a/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_view.cpp b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_view.cpp index 8ee134d35..5edb04379 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_view.cpp +++ b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_view.cpp @@ -21,15 +21,170 @@ #include "UnitTestUtils/EWK2UnitTestBase.h" #include "UnitTestUtils/EWK2UnitTestEnvironment.h" +#include "UnitTestUtils/EWK2UnitTestServer.h" #include <EWebKit2.h> +#include <Ecore.h> #include <gtest/gtest.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/UnusedParam.h> +#include <wtf/text/CString.h> using namespace EWK2UnitTest; extern EWK2UnitTestEnvironment* environment; +static void onLoadFinishedForRedirection(void* userData, Evas_Object*, void*) +{ + int* countLoadFinished = static_cast<int*>(userData); + (*countLoadFinished)--; +} + TEST_F(EWK2UnitTestBase, ewk_view_uri_get) { loadUrlSync(environment->defaultTestPageUrl()); EXPECT_STREQ(ewk_view_uri_get(webView()), environment->defaultTestPageUrl()); + + int countLoadFinished = 2; + evas_object_smart_callback_add(webView(), "load,finished", onLoadFinishedForRedirection, &countLoadFinished); + ewk_view_uri_set(webView(), environment->urlForResource("redirect_uri_to_default.html").data()); + while (countLoadFinished) + ecore_main_loop_iterate(); + evas_object_smart_callback_del(webView(), "load,finished", onLoadFinishedForRedirection); + EXPECT_STREQ(ewk_view_uri_get(webView()), environment->defaultTestPageUrl()); +} + +TEST_F(EWK2UnitTestBase, ewk_view_device_pixel_ratio) +{ + loadUrlSync(environment->defaultTestPageUrl()); + + // Default pixel ratio is 1.0 + ASSERT_FLOAT_EQ(ewk_view_device_pixel_ratio_get(webView()), 1); + + ASSERT_TRUE(ewk_view_device_pixel_ratio_set(webView(), 1.2)); + ASSERT_FLOAT_EQ(ewk_view_device_pixel_ratio_get(webView()), 1.2); + + ASSERT_TRUE(ewk_view_device_pixel_ratio_set(webView(), 1)); + ASSERT_FLOAT_EQ(ewk_view_device_pixel_ratio_get(webView()), 1); +} + +TEST_F(EWK2UnitTestBase, ewk_view_html_string_load) +{ + ewk_view_html_string_load(webView(), "<html><head><title>Foo</title></head><body>Bar</body></html>", 0, 0); + waitUntilTitleChangedTo("Foo"); + ASSERT_STREQ(ewk_view_title_get(webView()), "Foo"); + ewk_view_html_string_load(webView(), "<html><head><title>Bar</title></head><body>Foo</body></html>", 0, 0); + waitUntilTitleChangedTo("Bar"); + ASSERT_STREQ(ewk_view_title_get(webView()), "Bar"); +} + +static void serverCallbackNavigation(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) +{ + if (message->method != SOUP_METHOD_GET) { + soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status(message, SOUP_STATUS_OK); + + Eina_Strbuf* body = eina_strbuf_new(); + eina_strbuf_append_printf(body, "<html><title>%s</title><body>%s</body></html>", path + 1, path + 1); + const size_t bodyLength = eina_strbuf_length_get(body); + soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, eina_strbuf_string_steal(body), bodyLength); + eina_strbuf_free(body); + + soup_message_body_complete(message->response_body); +} + +TEST_F(EWK2UnitTestBase, ewk_view_navigation) +{ + OwnPtr<EWK2UnitTestServer> httpServer = adoptPtr(new EWK2UnitTestServer); + httpServer->run(serverCallbackNavigation); + + // Visit Page1 + loadUrlSync(httpServer->getURIForPath("/Page1").data()); + ASSERT_STREQ(ewk_view_title_get(webView()), "Page1"); + ASSERT_FALSE(ewk_view_back_possible(webView())); + ASSERT_FALSE(ewk_view_forward_possible(webView())); + + // Visit Page2 + loadUrlSync(httpServer->getURIForPath("/Page2").data()); + ASSERT_STREQ(ewk_view_title_get(webView()), "Page2"); + ASSERT_TRUE(ewk_view_back_possible(webView())); + ASSERT_FALSE(ewk_view_forward_possible(webView())); + + // Go back to Page1 + ewk_view_back(webView()); + waitUntilTitleChangedTo("Page1"); + ASSERT_STREQ(ewk_view_title_get(webView()), "Page1"); + ASSERT_FALSE(ewk_view_back_possible(webView())); + ASSERT_TRUE(ewk_view_forward_possible(webView())); + + // Go forward to Page2 + ewk_view_forward(webView()); + waitUntilTitleChangedTo("Page2"); + ASSERT_STREQ(ewk_view_title_get(webView()), "Page2"); + ASSERT_TRUE(ewk_view_back_possible(webView())); + ASSERT_FALSE(ewk_view_forward_possible(webView())); +} + +TEST_F(EWK2UnitTestBase, ewk_view_setting_encoding_custom) +{ + ASSERT_FALSE(ewk_view_setting_encoding_custom_get(webView())); + ASSERT_TRUE(ewk_view_setting_encoding_custom_set(webView(), "UTF-8")); + ASSERT_STREQ(ewk_view_setting_encoding_custom_get(webView()), "UTF-8"); + // Set the default charset. + ASSERT_TRUE(ewk_view_setting_encoding_custom_set(webView(), 0)); + ASSERT_FALSE(ewk_view_setting_encoding_custom_get(webView())); +} + +static void onFormAboutToBeSubmitted(void* userData, Evas_Object*, void* eventInfo) +{ + Ewk_Form_Submission_Request* request = static_cast<Ewk_Form_Submission_Request*>(eventInfo); + bool* handled = static_cast<bool*>(userData); + + ASSERT_TRUE(request); + + Eina_List* fieldNames = ewk_form_submission_request_field_names_get(request); + ASSERT_TRUE(fieldNames); + ASSERT_EQ(eina_list_count(fieldNames), 3); + void* data; + EINA_LIST_FREE(fieldNames, data) + eina_stringshare_del(static_cast<char*>(data)); + + const char* value1 = ewk_form_submission_request_field_value_get(request, "text1"); + ASSERT_STREQ(value1, "value1"); + eina_stringshare_del(value1); + const char* value2 = ewk_form_submission_request_field_value_get(request, "text2"); + ASSERT_STREQ(value2, "value2"); + eina_stringshare_del(value2); + const char* password = ewk_form_submission_request_field_value_get(request, "password"); + ASSERT_STREQ(password, "secret"); + eina_stringshare_del(password); + + *handled = true; +} + +TEST_F(EWK2UnitTestBase, ewk_view_form_submission_request) +{ + const char* formHTML = + "<html><head><script type='text/javascript'>function submitForm() { document.getElementById('myform').submit(); }</script></head>" + "<body onload='submitForm()'>" + " <form id='myform' action='#'>" + " <input type='text' name='text1' value='value1'>" + " <input type='text' name='text2' value='value2'>" + " <input type='password' name='password' value='secret'>" + " <textarea cols='5' rows='5' name='textarea'>Text</textarea>" + " <input type='hidden' name='hidden1' value='hidden1'>" + " <input type='submit' value='Submit'>" + " </form>" + "</body></html>"; + + ewk_view_html_string_load(webView(), formHTML, "file:///", 0); + bool handled = false; + evas_object_smart_callback_add(webView(), "form,submission,request", onFormAboutToBeSubmitted, &handled); + while (!handled) + ecore_main_loop_iterate(); + ASSERT_TRUE(handled); + evas_object_smart_callback_del(webView(), "form,submission,request", onFormAboutToBeSubmitted); } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h index 7fd5d7861..aa8a71bf9 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h @@ -40,6 +40,7 @@ #include <WebKit2/WKSerializedScriptValue.h> #include <WebKit2/WKSoupRequestManager.h> #include <WebKit2/WKString.h> +#include <WebKit2/WKTextChecker.h> #include <WebKit2/WebKit2.h> #include <glib.h> #include <wtf/Assertions.h> diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitTextChecker.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitTextChecker.cpp new file mode 100644 index 000000000..5676bb6d7 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitTextChecker.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebKitTextChecker.h" + +#if ENABLE(SPELLCHECK) + +#include "WebKitPrivate.h" +#include <wtf/Vector.h> +#include <wtf/text/CString.h> + +using namespace WebKit; + +static inline WebKitTextChecker* toTextChecker(const void* clientInfo) +{ + return static_cast<WebKitTextChecker*>(const_cast<void*>(clientInfo)); +} + +static bool continuousSpellCheckingEnabledCallback(const void* clientInfo) +{ + return toTextChecker(clientInfo)->isSpellCheckingEnabled(); +} + +static void setContinuousSpellCheckingEnabledCallback(bool enabled, const void* clientInfo) +{ + toTextChecker(clientInfo)->setSpellCheckingEnabled(enabled); +} + +static void checkSpellingOfStringCallback(uint64_t tag, WKStringRef text, int32_t* misspellingLocation, int32_t* misspellingLength, const void* clientInfo) +{ + toTextChecker(clientInfo)->checkSpellingOfString(toImpl(text)->string(), *misspellingLocation, *misspellingLength); +} + +static WKArrayRef guessesForWordCallback(uint64_t tag, WKStringRef word, const void* clientInfo) +{ + Vector<String> guesses = toTextChecker(clientInfo)->getGuessesForWord(toImpl(word)->string()); + if (guesses.isEmpty()) + return 0; + + WKMutableArrayRef wkSuggestions = WKMutableArrayCreate(); + for (Vector<String>::const_iterator iter = guesses.begin(); iter != guesses.end(); ++iter) { + WKRetainPtr<WKStringRef> wkSuggestion(AdoptWK, WKStringCreateWithUTF8CString(iter->utf8().data())); + WKArrayAppendItem(wkSuggestions, wkSuggestion.get()); + } + + return wkSuggestions; +} + +static void learnWordCallback(uint64_t tag, WKStringRef word, const void* clientInfo) +{ + toTextChecker(clientInfo)->learnWord(toImpl(word)->string()); +} + +static void ignoreWordCallback(uint64_t tag, WKStringRef word, const void* clientInfo) +{ + toTextChecker(clientInfo)->ignoreWord(toImpl(word)->string()); +} + +WebKitTextChecker::~WebKitTextChecker() +{ +} + +WebKitTextChecker::WebKitTextChecker() + : m_textChecker(WebCore::TextCheckerEnchant::create()) + , m_spellCheckingEnabled(false) +{ + WKTextCheckerClient wkTextCheckerClient = { + kWKTextCheckerClientCurrentVersion, + this, // clientInfo + 0, // continuousSpellCheckingAllowed + continuousSpellCheckingEnabledCallback, + setContinuousSpellCheckingEnabledCallback, + 0, // grammarCheckingEnabled + 0, // setGrammarCheckingEnabled + 0, // uniqueSpellDocumentTag + 0, // closeSpellDocumentWithTag + checkSpellingOfStringCallback, + 0, // checkGrammarOfString + 0, // spellingUIIsShowing + 0, // toggleSpellingUIIsShowing + 0, // updateSpellingUIWithMisspelledWord + 0, // updateSpellingUIWithGrammarString + guessesForWordCallback, + learnWordCallback, + ignoreWordCallback, + }; + WKTextCheckerSetClient(&wkTextCheckerClient); +} + +void WebKitTextChecker::checkSpellingOfString(const String& string, int& misspellingLocation, int& misspellingLength) +{ + m_textChecker->checkSpellingOfString(string, misspellingLocation, misspellingLength); +} + +Vector<String> WebKitTextChecker::getGuessesForWord(const String& word) +{ + return m_textChecker->getGuessesForWord(word); +} + +void WebKitTextChecker::learnWord(const String& word) +{ + m_textChecker->learnWord(word); +} + +void WebKitTextChecker::ignoreWord(const String& word) +{ + m_textChecker->ignoreWord(word); +} + +void WebKitTextChecker::setSpellCheckingEnabled(bool enabled) +{ + if (m_spellCheckingEnabled == enabled) + return; + m_spellCheckingEnabled = enabled; + + // We need to notify the Web process that this has changed. + WKTextCheckerContinuousSpellCheckingEnabledStateChanged(enabled); +} + +void WebKitTextChecker::setSpellCheckingLanguages(const String& languages) +{ + if (m_spellCheckingLanguages == languages) + return; + m_spellCheckingLanguages = languages; + + // We need to update the languages in the enchant-based checker too. + m_textChecker->updateSpellCheckingLanguages(languages); +} +#endif // ENABLE(SPELLCHECK) diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitTextChecker.h b/Source/WebKit2/UIProcess/API/gtk/WebKitTextChecker.h new file mode 100644 index 000000000..dd7583a3a --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitTextChecker.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitTextChecker_h +#define WebKitTextChecker_h + +#if ENABLE(SPELLCHECK) + +#include <WebCore/TextCheckerEnchant.h> +#include <wtf/FastAllocBase.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/Vector.h> + +class WebKitTextChecker { + WTF_MAKE_FAST_ALLOCATED; + +public: + static PassOwnPtr<WebKitTextChecker> create() { return adoptPtr(new WebKitTextChecker()); } + virtual ~WebKitTextChecker(); + + // For implementing TextCheckerClient. + bool isSpellCheckingEnabled() { return m_spellCheckingEnabled; } + void setSpellCheckingEnabled(bool enabled); + void checkSpellingOfString(const String& string, int& misspellingLocation, int& misspellingLength); + Vector<String> getGuessesForWord(const String& word); + void learnWord(const String& word); + void ignoreWord(const String& word); + + // To be called from WebKitWebContext only. + const String getSpellCheckingLanguages() { return m_spellCheckingLanguages; } + void setSpellCheckingLanguages(const String& spellCheckingLanguages); + +private: + WebKitTextChecker(); + + OwnPtr<WebCore::TextCheckerEnchant> m_textChecker; + String m_spellCheckingLanguages; + bool m_spellCheckingEnabled; +}; + +#endif // ENABLE(SPELLCHECK) + +#endif // WebKitTextChecker_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp index 8a0625c07..4008e865f 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp @@ -28,10 +28,13 @@ #include "WebKitPluginPrivate.h" #include "WebKitPrivate.h" #include "WebKitRequestManagerClient.h" +#include "WebKitTextChecker.h" #include "WebKitURISchemeRequestPrivate.h" #include "WebKitWebContextPrivate.h" #include <WebCore/FileSystem.h> #include <wtf/HashMap.h> +#include <wtf/OwnPtr.h> +#include <wtf/gobject/GOwnPtr.h> #include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> @@ -72,6 +75,10 @@ struct _WebKitWebContextPrivate { #if ENABLE(GEOLOCATION) RefPtr<WebKitGeolocationProvider> geolocationProvider; #endif +#if ENABLE(SPELLCHECK) + OwnPtr<WebKitTextChecker> textChecker; + GOwnPtr<gchar> spellCheckingLanguages; +#endif }; static guint signals[LAST_SIGNAL] = { 0, }; @@ -127,6 +134,9 @@ static gpointer createDefaultWebContext(gpointer) WKGeolocationManagerRef wkGeolocationManager = WKContextGetGeolocationManager(webContext->priv->context.get()); webContext->priv->geolocationProvider = WebKitGeolocationProvider::create(wkGeolocationManager); #endif +#if ENABLE(SPELLCHECK) + webContext->priv->textChecker = WebKitTextChecker::create(); +#endif return webContext.get(); } @@ -418,6 +428,88 @@ void webkit_web_context_register_uri_scheme(WebKitWebContext* context, const cha WKSoupRequestManagerRegisterURIScheme(context->priv->requestManager.get(), wkScheme.get()); } +/** + * webkit_web_context_get_spell_checking_enabled: + * @context: a #WebKitWebContext + * + * Get the current status of the spell checking feature. + * + * Returns: %TRUE If spell checking is enabled, or %FALSE otherwise. + */ +gboolean webkit_web_context_get_spell_checking_enabled(WebKitWebContext* context) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), FALSE); + +#if ENABLE(SPELLCHECK) + return context->priv->textChecker->isSpellCheckingEnabled(); +#else + return false; +#endif +} + +/** + * webkit_web_context_set_spell_checking_enabled: + * @context: a #WebKitWebContext + * @enabled: Value to be set + * + * Enable or disable the spell checking feature. + */ +void webkit_web_context_set_spell_checking_enabled(WebKitWebContext* context, gboolean enabled) +{ + g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); + +#if ENABLE(SPELLCHECK) + context->priv->textChecker->setSpellCheckingEnabled(enabled); +#endif +} + +/** + * webkit_web_context_get_spell_checking_languages: + * @context: a #WebKitWebContext + * + * Get the the list of spell checking languages associated with + * @context, separated by commas. See + * webkit_web_context_set_spell_checking_languages() for more details + * on the format of the languages in the list. + * + * Returns: (transfer none): A comma separated list of languages. + */ +const gchar* webkit_web_context_get_spell_checking_languages(WebKitWebContext* context) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); + +#if ENABLE(SPELLCHECK) + return context->priv->spellCheckingLanguages.get(); +#else + return 0; +#endif +} + +/** + * webkit_web_context_set_spell_checking_languages: + * @context: a #WebKitWebContext + * @languages: (allow-none): new list of spell checking + * languages separated by commas, or %NULL + * + * Set the list of spell checking languages to be used for spell + * checking, separated by commas. In case %NULL is passed, the default + * value as returned by gtk_get_default_language() will be used. + * + * The locale string typically is in the form lang_COUNTRY, where lang + * is an ISO-639 language code, and COUNTRY is an ISO-3166 country code. + * For instance, sv_FI for Swedish as written in Finland or pt_BR + * for Portuguese as written in Brazil. + */ +void webkit_web_context_set_spell_checking_languages(WebKitWebContext* context, const gchar* languages) +{ + g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); + +#if ENABLE(SPELLCHECK) + context->priv->textChecker->setSpellCheckingLanguages(String(languages)); + context->priv->spellCheckingLanguages.set(g_strdup(languages)); +#endif +} + WebKitDownload* webkitWebContextGetOrCreateDownload(WKDownloadRef wkDownload) { GRefPtr<WebKitDownload> download = downloadsMap().get(wkDownload); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h index 83b601a38..0d32ba5bb 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h @@ -132,6 +132,20 @@ webkit_web_context_register_uri_scheme (WebKitWebContext const gchar *scheme, WebKitURISchemeRequestCallback callback, gpointer user_data); + +WEBKIT_API gboolean +webkit_web_context_get_spell_checking_enabled (WebKitWebContext *context); + +WEBKIT_API void +webkit_web_context_set_spell_checking_enabled (WebKitWebContext *context, + gboolean enabled); +WEBKIT_API const gchar * +webkit_web_context_get_spell_checking_languages (WebKitWebContext *context); + +WEBKIT_API void +webkit_web_context_set_spell_checking_languages (WebKitWebContext *context, + const gchar *languages); + G_END_DECLS #endif diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt index 3164177cc..73f09d5d3 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt @@ -33,6 +33,10 @@ webkit_web_context_get_cookie_manager webkit_web_context_set_additional_plugins_directory webkit_web_context_get_plugins webkit_web_context_get_plugins_finish +webkit_web_context_get_spell_checking_enabled +webkit_web_context_set_spell_checking_enabled +webkit_web_context_get_spell_checking_languages +webkit_web_context_set_spell_checking_languages <SUBSECTION URI Scheme> WebKitURISchemeRequestCallback diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp index e7d43a13d..f42feafb7 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp @@ -231,11 +231,38 @@ static void testWebContextURIScheme(URISchemeTest* test, gconstpointer) g_assert(!test->m_loadEvents.contains(LoadTrackingTest::LoadFailed)); } +static void testWebContextSpellChecker(Test* test, gconstpointer) +{ + GRefPtr<WebKitWebContext> webContext(webkit_web_context_get_default()); + + // Set the language to a specific one, an empty one and a list of them. + webkit_web_context_set_spell_checking_languages(webContext.get(), "en_US"); + const gchar* currentLanguage(webkit_web_context_get_spell_checking_languages(webContext.get())); + g_assert_cmpstr(currentLanguage, ==, "en_US"); + + webkit_web_context_set_spell_checking_languages(webContext.get(), 0); + currentLanguage = webkit_web_context_get_spell_checking_languages(webContext.get()); + g_assert_cmpstr(currentLanguage, ==, 0); + + webkit_web_context_set_spell_checking_languages(webContext.get(), "es_ES,en_US"); + currentLanguage = webkit_web_context_get_spell_checking_languages(webContext.get()); + g_assert_cmpstr(currentLanguage, ==, "es_ES,en_US"); + + // Check disabling and re-enabling spell checking. + webkit_web_context_set_spell_checking_enabled(webContext.get(), FALSE); + gboolean isSpellCheckingEnabled = webkit_web_context_get_spell_checking_enabled(webContext.get()); + g_assert(!isSpellCheckingEnabled); + webkit_web_context_set_spell_checking_enabled(webContext.get(), TRUE); + isSpellCheckingEnabled = webkit_web_context_get_spell_checking_enabled(webContext.get()); + g_assert(isSpellCheckingEnabled); +} + void beforeAll() { Test::add("WebKitWebContext", "default-context", testWebContextDefault); PluginsTest::add("WebKitWebContext", "get-plugins", testWebContextGetPlugins); URISchemeTest::add("WebKitWebContext", "uri-scheme", testWebContextURIScheme); + Test::add("WebKitWebContext", "spell-checker", testWebContextSpellChecker); } void afterAll() diff --git a/Source/WebKit2/UIProcess/API/mac/WKView.mm b/Source/WebKit2/UIProcess/API/mac/WKView.mm index 27f233b69..a11ef65d0 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKView.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKView.mm @@ -1201,6 +1201,7 @@ static const short kIOHIDEventTypeScroll = 6; // - If it's sent outside of keyboard event processing (e.g. from Character Viewer, or when confirming an inline input area with a mouse), // then we also execute it immediately, as there will be no other chance. if (parameters && !isFromInputMethod) { + // FIXME: Handle replacementRange in this case, too. It's known to occur in practice when canceling Press and Hold (see <rdar://11940670>). ASSERT(replacementRange.location == NSNotFound); KeypressCommand command("insertText:", text); parameters->commands->append(command); @@ -1272,6 +1273,7 @@ static const short kIOHIDEventTypeScroll = 6; - (void)keyUp:(NSEvent *)theEvent { + LOG(TextInput, "keyUp:%p %@", theEvent, theEvent); _data->_page->handleKeyboardEvent(NativeWebKeyboardEvent(theEvent, self)); } @@ -1326,13 +1328,17 @@ static const short kIOHIDEventTypeScroll = 6; - (void)keyDown:(NSEvent *)theEvent { + LOG(TextInput, "keyDown:%p %@%s", theEvent, theEvent, (theEvent == _data->_keyDownEventBeingResent) ? " (re-sent)" : ""); + // There's a chance that responding to this event will run a nested event loop, and // fetching a new event might release the old one. Retaining and then autoreleasing // the current event prevents that from causing a problem inside WebKit or AppKit code. [[theEvent retain] autorelease]; - if ([self _tryHandlePluginComplexTextInputKeyDown:theEvent]) + if ([self _tryHandlePluginComplexTextInputKeyDown:theEvent]) { + LOG(TextInput, "...handled by plug-in"); return; + } // We could be receiving a key down from AppKit if we have re-sent an event // that maps to an action that is currently unavailable (for example a copy when @@ -1347,6 +1353,8 @@ static const short kIOHIDEventTypeScroll = 6; - (void)flagsChanged:(NSEvent *)theEvent { + LOG(TextInput, "flagsChanged:%p %@", theEvent, theEvent); + // There's a chance that responding to this event will run a nested event loop, and // fetching a new event might release the old one. Retaining and then autoreleasing // the current event prevents that from causing a problem inside WebKit or AppKit code. @@ -1372,10 +1380,14 @@ static const short kIOHIDEventTypeScroll = 6; if (parameters->executingSavedKeypressCommands) return; + LOG(TextInput, "Executing %u saved keypress commands...", parameters->commands->size()); + parameters->executingSavedKeypressCommands = true; parameters->eventInterpretationHadSideEffects |= _data->_page->executeKeypressCommands(*parameters->commands); parameters->commands->clear(); parameters->executingSavedKeypressCommands = false; + + LOG(TextInput, "...done executing saved keypress commands."); } - (void)_notifyInputContextAboutDiscardedComposition @@ -1386,6 +1398,7 @@ static const short kIOHIDEventTypeScroll = 6; if (![[self window] isKeyWindow] || self != [[self window] firstResponder]) return; + LOG(TextInput, "-> discardMarkedText"); [[super inputContext] discardMarkedText]; // Inform the input method that we won't have an inline input area despite having been asked to. } @@ -2371,14 +2384,19 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I parameters.commands = &commands; _data->_interpretKeyEventsParameters = ¶meters; + LOG(TextInput, "-> interpretKeyEvents:%p %@", event, event); [self interpretKeyEvents:[NSArray arrayWithObject:event]]; _data->_interpretKeyEventsParameters = 0; // An input method may consume an event and not tell us (e.g. when displaying a candidate window), // in which case we should not bubble the event up the DOM. - if (parameters.consumedByIM) + if (parameters.consumedByIM) { + LOG(TextInput, "...event %p was consumed by an input method", event); return YES; + } + + LOG(TextInput, "...interpretKeyEvents for event %p done, returns %d", event, parameters.eventInterpretationHadSideEffects); // If we have already executed all or some of the commands, the event is "handled". Note that there are additional checks on web process side. return parameters.eventInterpretationHadSideEffects; @@ -2827,10 +2845,12 @@ static NSString *pathWithUniqueFilenameForPath(NSString *path) if (!_data->_inSecureInputState) EnableSecureEventInput(); static NSArray *romanInputSources = [[NSArray alloc] initWithObjects:&NSAllRomanInputSourcesLocaleIdentifier count:1]; + LOG(TextInput, "-> setAllowedInputSourceLocales:romanInputSources"); [context setAllowedInputSourceLocales:romanInputSources]; } else { if (_data->_inSecureInputState) DisableSecureEventInput(); + LOG(TextInput, "-> setAllowedInputSourceLocales:nil"); [context setAllowedInputSourceLocales:nil]; } _data->_inSecureInputState = isInPasswordField; |