diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-09-10 19:10:20 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-09-10 19:10:20 +0200 |
commit | 284837daa07b29d6a63a748544a90b1f5842ac5c (patch) | |
tree | ecd258180bde91fe741e0cfd2638beb3c6da7e8e /Source/WebKit2/UIProcess | |
parent | 2e2ba8ff45915f40ed3e014101269c175f2a89a0 (diff) | |
download | qtwebkit-284837daa07b29d6a63a748544a90b1f5842ac5c.tar.gz |
Imported WebKit commit 68645295d2e3e09af2c942f092556f06aa5f8b0d (http://svn.webkit.org/repository/webkit/trunk@128073)
New snapshot
Diffstat (limited to 'Source/WebKit2/UIProcess')
115 files changed, 3562 insertions, 1274 deletions
diff --git a/Source/WebKit2/UIProcess/API/C/WKAPICast.h b/Source/WebKit2/UIProcess/API/C/WKAPICast.h index bef294e8a..fe55dd8ac 100644 --- a/Source/WebKit2/UIProcess/API/C/WKAPICast.h +++ b/Source/WebKit2/UIProcess/API/C/WKAPICast.h @@ -30,12 +30,14 @@ #include "CacheModel.h" #include "FontSmoothingLevel.h" #include "HTTPCookieAcceptPolicy.h" +#include "ProcessModel.h" #include "ResourceCachesToClear.h" #include "WebGrammarDetail.h" #include "WKContext.h" #include "WKCookieManager.h" #include "WKCredentialTypes.h" #include "WKPage.h" +#include "WKPreferences.h" #include "WKPreferencesPrivate.h" #include "WKProtectionSpaceTypes.h" #include "WKResourceCacheManager.h" @@ -174,6 +176,31 @@ inline WKCacheModel toAPI(CacheModel cacheModel) return kWKCacheModelDocumentViewer; } +inline ProcessModel toProcessModel(WKProcessModel wkProcessModel) +{ + switch (wkProcessModel) { + case kWKProcessModelSharedSecondaryProcess: + return ProcessModelSharedSecondaryProcess; + case kWKProcessModelMultipleSecondaryProcesses: + return ProcessModelMultipleSecondaryProcesses; + } + + ASSERT_NOT_REACHED(); + return ProcessModelSharedSecondaryProcess; +} + +inline WKProcessModel toAPI(ProcessModel processModel) +{ + switch (processModel) { + case ProcessModelSharedSecondaryProcess: + return kWKProcessModelSharedSecondaryProcess; + case ProcessModelMultipleSecondaryProcesses: + return kWKProcessModelMultipleSecondaryProcesses; + } + + return kWKProcessModelSharedSecondaryProcess; +} + inline FontSmoothingLevel toFontSmoothingLevel(WKFontSmoothingLevel wkLevel) { switch (wkLevel) { @@ -359,6 +386,36 @@ inline WKHTTPCookieAcceptPolicy toAPI(HTTPCookieAcceptPolicy policy) return kWKHTTPCookieAcceptPolicyAlways; } +inline WebCore::SecurityOrigin::StorageBlockingPolicy toStorageBlockingPolicy(WKStorageBlockingPolicy policy) +{ + switch (policy) { + case kWKAllowAllStorage: + return WebCore::SecurityOrigin::AllowAllStorage; + case kWKBlockThirdPartyStorage: + return WebCore::SecurityOrigin::BlockThirdPartyStorage; + case kWKBlockAllStorage: + return WebCore::SecurityOrigin::BlockAllStorage; + } + + ASSERT_NOT_REACHED(); + return WebCore::SecurityOrigin::AllowAllStorage; +} + +inline WKStorageBlockingPolicy toAPI(WebCore::SecurityOrigin::StorageBlockingPolicy policy) +{ + switch (policy) { + case WebCore::SecurityOrigin::AllowAllStorage: + return kWKAllowAllStorage; + case WebCore::SecurityOrigin::BlockThirdPartyStorage: + return kWKBlockThirdPartyStorage; + case WebCore::SecurityOrigin::BlockAllStorage: + return kWKBlockAllStorage; + } + + ASSERT_NOT_REACHED(); + return kWKAllowAllStorage; +} + inline ProxyingRefPtr<WebGrammarDetail> toAPI(const WebCore::GrammarDetail& grammarDetail) { return ProxyingRefPtr<WebGrammarDetail>(WebGrammarDetail::create(grammarDetail)); @@ -366,7 +423,7 @@ inline ProxyingRefPtr<WebGrammarDetail> toAPI(const WebCore::GrammarDetail& gram } // namespace WebKit -#if defined(WIN32) || defined(_WIN32) +#if (defined(WIN32) || defined(_WIN32)) && !defined(BUILDING_QT__) #include "WKAPICastWin.h" #endif diff --git a/Source/WebKit2/UIProcess/API/C/WKContext.cpp b/Source/WebKit2/UIProcess/API/C/WKContext.cpp index f802e9374..28a70821b 100644 --- a/Source/WebKit2/UIProcess/API/C/WKContext.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKContext.cpp @@ -120,6 +120,16 @@ WKCacheModel WKContextGetCacheModel(WKContextRef contextRef) return toAPI(toImpl(contextRef)->cacheModel()); } +void WKContextSetProcessModel(WKContextRef contextRef, WKProcessModel processModel) +{ + toImpl(contextRef)->setProcessModel(toProcessModel(processModel)); +} + +WKProcessModel WKContextGetProcessModel(WKContextRef contextRef) +{ + return toAPI(toImpl(contextRef)->processModel()); +} + void WKContextSetAlwaysUsesComplexTextCodePath(WKContextRef contextRef, bool alwaysUseComplexTextCodePath) { toImpl(contextRef)->setAlwaysUsesComplexTextCodePath(alwaysUseComplexTextCodePath); diff --git a/Source/WebKit2/UIProcess/API/C/WKContext.h b/Source/WebKit2/UIProcess/API/C/WKContext.h index 967daea79..69d129805 100644 --- a/Source/WebKit2/UIProcess/API/C/WKContext.h +++ b/Source/WebKit2/UIProcess/API/C/WKContext.h @@ -123,6 +123,12 @@ typedef struct WKContextConnectionClient WKContextConnectionClient; enum { kWKContextConnectionClientCurrentVersion = 0 }; +enum { + kWKProcessModelSharedSecondaryProcess = 0, + kWKProcessModelMultipleSecondaryProcesses = 1 +}; +typedef uint32_t WKProcessModel; + WK_EXPORT WKTypeID WKContextGetTypeID(); WK_EXPORT WKContextRef WKContextCreate(); @@ -143,6 +149,9 @@ WK_EXPORT void WKContextAddVisitedLink(WKContextRef context, WKStringRef visited WK_EXPORT void WKContextSetCacheModel(WKContextRef context, WKCacheModel cacheModel); WK_EXPORT WKCacheModel WKContextGetCacheModel(WKContextRef context); +WK_EXPORT void WKContextSetProcessModel(WKContextRef context, WKProcessModel processModel); +WK_EXPORT WKProcessModel WKContextGetProcessModel(WKContextRef context); + WK_EXPORT void WKContextStartMemorySampler(WKContextRef context, WKDoubleRef interval); WK_EXPORT void WKContextStopMemorySampler(WKContextRef context); diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp b/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp index 66d4dcd98..862e2d1b0 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp @@ -817,14 +817,14 @@ bool WKPreferencesGetRequestAnimationFrameEnabled(WKPreferencesRef preferencesRe return toImpl(preferencesRef)->requestAnimationFrameEnabled(); } -void WKPreferencesSetThirdPartyStorageBlockingEnabled(WKPreferencesRef preferencesRef, bool flag) +void WKPreferencesSetStorageBlockingPolicy(WKPreferencesRef preferencesRef, WKStorageBlockingPolicy policy) { - toImpl(preferencesRef)->setThirdPartyStorageBlockingEnabled(flag); + toImpl(preferencesRef)->setStorageBlockingPolicy(toStorageBlockingPolicy(policy)); } -bool WKPreferencesGetThirdPartyStorageBlockingEnabled(WKPreferencesRef preferencesRef) +WKStorageBlockingPolicy WKPreferencesGetStorageBlockingPolicy(WKPreferencesRef preferencesRef) { - return toImpl(preferencesRef)->thirdPartyStorageBlockingEnabled(); + return toAPI(static_cast<WebCore::SecurityOrigin::StorageBlockingPolicy>(toImpl(preferencesRef)->storageBlockingPolicy())); } void WKPreferencesResetTestRunnerOverrides(WKPreferencesRef preferencesRef) @@ -874,6 +874,26 @@ bool WKPreferencesGetArtificialPluginInitializationDelayEnabled(WKPreferencesRef return toImpl(preferencesRef)->artificialPluginInitializationDelayEnabled(); } +void WKPreferencesSetTabToLinksEnabled(WKPreferencesRef preferencesRef, bool enabled) +{ + toImpl(preferencesRef)->setTabToLinksEnabled(enabled); +} + +bool WKPreferencesGetTabToLinksEnabled(WKPreferencesRef preferencesRef) +{ + return toImpl(preferencesRef)->tabToLinksEnabled(); +} + +void WKPreferencesSetInteractiveFormValidationEnabled(WKPreferencesRef preferencesRef, bool enabled) +{ + toImpl(preferencesRef)->setInteractiveFormValidationEnabled(enabled); +} + +bool WKPreferencesGetInteractiveFormValidationEnabled(WKPreferencesRef preferencesRef) +{ + return toImpl(preferencesRef)->interactiveFormValidationEnabled(); +} + void WKPreferencesSetScrollingPerformanceLoggingEnabled(WKPreferencesRef preferencesRef, bool enabled) { toImpl(preferencesRef)->setScrollingPerformanceLoggingEnabled(enabled); diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferences.h b/Source/WebKit2/UIProcess/API/C/WKPreferences.h index 883fbff61..c0fde67fd 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferences.h +++ b/Source/WebKit2/UIProcess/API/C/WKPreferences.h @@ -36,6 +36,13 @@ extern "C" { #endif +enum WKStorageBlockingPolicy { + kWKAllowAllStorage = 0, + kWKBlockThirdPartyStorage, + kWKBlockAllStorage +}; +typedef enum WKStorageBlockingPolicy WKStorageBlockingPolicy; + WK_EXPORT WKTypeID WKPreferencesGetTypeID(); WK_EXPORT WKPreferencesRef WKPreferencesCreate(); @@ -206,8 +213,8 @@ WK_EXPORT void WKPreferencesSetShouldRespectImageOrientation(WKPreferencesRef pr WK_EXPORT bool WKPreferencesGetShouldRespectImageOrientation(WKPreferencesRef preferencesRef); // Defaults to false -WK_EXPORT void WKPreferencesSetThirdPartyStorageBlockingEnabled(WKPreferencesRef preferencesRef, bool enabled); -WK_EXPORT bool WKPreferencesGetThirdPartyStorageBlockingEnabled(WKPreferencesRef preferencesRef); +WK_EXPORT void WKPreferencesSetStorageBlockingPolicy(WKPreferencesRef preferencesRef, WKStorageBlockingPolicy policy); +WK_EXPORT WKStorageBlockingPolicy WKPreferencesGetStorageBlockingPolicy(WKPreferencesRef preferencesRef); #ifdef __cplusplus } diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h b/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h index b469d7aca..31899d47e 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h +++ b/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h @@ -204,6 +204,14 @@ WK_EXPORT void WKPreferencesSetArtificialPluginInitializationDelayEnabled(WKPref WK_EXPORT bool WKPreferencesGetArtificialPluginInitializationDelayEnabled(WKPreferencesRef preferencesRef); // Defaults to false +WK_EXPORT void WKPreferencesSetTabToLinksEnabled(WKPreferencesRef preferencesRef, bool enabled); +WK_EXPORT bool WKPreferencesGetTabToLinksEnabled(WKPreferencesRef preferencesRef); + +// Defaults to false +WK_EXPORT void WKPreferencesSetInteractiveFormValidationEnabled(WKPreferencesRef preferencesRef, bool enabled); +WK_EXPORT bool WKPreferencesGetInteractiveFormValidationEnabled(WKPreferencesRef preferencesRef); + +// Defaults to false WK_EXPORT void WKPreferencesSetScrollingPerformanceLoggingEnabled(WKPreferencesRef preferencesRef, bool enabled); WK_EXPORT bool WKPreferencesGetScrollingPerformanceLoggingEnabled(WKPreferencesRef preferencesRef); diff --git a/Source/WebKit2/UIProcess/API/efl/EWebKit2.h b/Source/WebKit2/UIProcess/API/efl/EWebKit2.h index d98023de6..750cb4864 100644 --- a/Source/WebKit2/UIProcess/API/efl/EWebKit2.h +++ b/Source/WebKit2/UIProcess/API/efl/EWebKit2.h @@ -38,6 +38,8 @@ #include "ewk_intent_service.h" #include "ewk_main.h" #include "ewk_navigation_policy_decision.h" +#include "ewk_popup_menu_item.h" +#include "ewk_settings.h" #include "ewk_url_request.h" #include "ewk_url_response.h" #include "ewk_url_scheme_request.h" diff --git a/Source/WebKit2/UIProcess/API/efl/EflViewportHandler.cpp b/Source/WebKit2/UIProcess/API/efl/EflViewportHandler.cpp index f5740822e..eb3d007fe 100644 --- a/Source/WebKit2/UIProcess/API/efl/EflViewportHandler.cpp +++ b/Source/WebKit2/UIProcess/API/efl/EflViewportHandler.cpp @@ -31,22 +31,28 @@ #include "LayerTreeCoordinatorProxy.h" #include "LayerTreeRenderer.h" #include "TransformationMatrix.h" +#include "ewk_view_private.h" using namespace WebCore; namespace WebKit { -EflViewportHandler::EflViewportHandler(PageClientImpl* pageClientImpl) - : m_pageClientImpl(pageClientImpl) +EflViewportHandler::EflViewportHandler(Evas_Object* viewWidget) + : m_viewWidget(viewWidget) , m_scaleFactor(1) { - ASSERT(m_pageClientImpl); + ASSERT(m_viewWidget); } EflViewportHandler::~EflViewportHandler() { } +DrawingAreaProxy* EflViewportHandler::drawingArea() const +{ + return ewk_view_page_get(m_viewWidget)->drawingArea(); +} + void EflViewportHandler::display(const IntRect& rect) { WebCore::TransformationMatrix matrix; @@ -61,7 +67,7 @@ void EflViewportHandler::display(const IntRect& rect) void EflViewportHandler::updateViewportSize(const IntSize& viewportSize) { m_viewportSize = viewportSize; - m_pageClientImpl->page()->setViewportSize(viewportSize); + ewk_view_page_get(m_viewWidget)->setViewportSize(viewportSize); setVisibleContentsRect(m_visibleContentRect.location(), m_scaleFactor, FloatPoint()); } diff --git a/Source/WebKit2/UIProcess/API/efl/EflViewportHandler.h b/Source/WebKit2/UIProcess/API/efl/EflViewportHandler.h index cc6b3d957..a23f4e147 100644 --- a/Source/WebKit2/UIProcess/API/efl/EflViewportHandler.h +++ b/Source/WebKit2/UIProcess/API/efl/EflViewportHandler.h @@ -35,13 +35,13 @@ namespace WebKit { class EflViewportHandler { public: - static PassOwnPtr<EflViewportHandler> create(PageClientImpl* pageClientImpl) + static PassOwnPtr<EflViewportHandler> create(Evas_Object* viewWidget) { - return adoptPtr(new EflViewportHandler(pageClientImpl)); + return adoptPtr(new EflViewportHandler(viewWidget)); } ~EflViewportHandler(); - DrawingAreaProxy* drawingArea() const { return m_pageClientImpl->page()->drawingArea(); } + DrawingAreaProxy* drawingArea() const; WebCore::IntSize viewSize() { return m_viewportSize; } void display(const WebCore::IntRect& rect); @@ -50,9 +50,9 @@ public: void didChangeContentsSize(const WebCore::IntSize& size); private: - explicit EflViewportHandler(PageClientImpl*); + explicit EflViewportHandler(Evas_Object*); - PageClientImpl* m_pageClientImpl; + Evas_Object* m_viewWidget; WebCore::IntRect m_visibleContentRect; WebCore::IntSize m_contentsSize; WebCore::IntSize m_viewportSize; diff --git a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp index 726caaae1..24bda6305 100644 --- a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp +++ b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp @@ -33,6 +33,7 @@ #include "WebContextMenuProxy.h" #include "WebPageGroup.h" #include "WebPageProxy.h" +#include "WebPopupMenuProxyEfl.h" #include "WebPreferences.h" #include "ewk_context.h" #include "ewk_context_private.h" @@ -44,18 +45,9 @@ using namespace WebCore; namespace WebKit { -PageClientImpl::PageClientImpl(WebContext* context, WebPageGroup* pageGroup, Evas_Object* viewWidget) +PageClientImpl::PageClientImpl(Evas_Object* viewWidget) : m_viewWidget(viewWidget) { - m_page = context->createWebPage(this, pageGroup); - -#if USE(COORDINATED_GRAPHICS) - m_page->pageGroup()->preferences()->setAcceleratedCompositingEnabled(true); - m_page->pageGroup()->preferences()->setForceCompositingMode(true); - m_page->setUseFixedLayout(true); -#endif - - m_page->initializeWebPage(); } PageClientImpl::~PageClientImpl() @@ -65,7 +57,7 @@ PageClientImpl::~PageClientImpl() // PageClient PassOwnPtr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy() { - return DrawingAreaProxyImpl::create(m_page.get()); + return DrawingAreaProxyImpl::create(ewk_view_page_get(m_viewWidget)); } void PageClientImpl::setViewNeedsDisplay(const WebCore::IntRect& rect) @@ -204,10 +196,9 @@ void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEven } #endif -PassRefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy*) +PassRefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy* page) { - notImplemented(); - return 0; + return WebPopupMenuProxyEfl::create(m_viewWidget, page); } PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy*) @@ -217,7 +208,7 @@ PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPagePr } #if ENABLE(INPUT_TYPE_COLOR) -PassRefPtr<WebColorChooserProxy> PageClientImpl::createColorChooserProxy(WebPageProxy*, const WebCore::Color&) +PassRefPtr<WebColorChooserProxy> PageClientImpl::createColorChooserProxy(WebPageProxy*, const WebCore::Color&, const WebCore::IntRect&) { notImplemented(); return 0; diff --git a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h index 861850263..36ee76d7d 100644 --- a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h +++ b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h @@ -33,18 +33,17 @@ namespace WebKit { class PageClientImpl : public PageClient { public: - static PassOwnPtr<PageClientImpl> create(WebContext* context, WebPageGroup* pageGroup, Evas_Object* viewWidget) + static PassOwnPtr<PageClientImpl> create(Evas_Object* viewWidget) { - return adoptPtr(new PageClientImpl(context, pageGroup, viewWidget)); + return adoptPtr(new PageClientImpl(viewWidget)); } ~PageClientImpl(); Evas_Object* viewWidget() const { return m_viewWidget; } - WebPageProxy* page() const { return m_page.get(); } private: - PageClientImpl(WebContext*, WebPageGroup*, Evas_Object*); + explicit PageClientImpl(Evas_Object*); // PageClient virtual PassOwnPtr<DrawingAreaProxy> createDrawingAreaProxy(); @@ -87,7 +86,7 @@ private: virtual PassRefPtr<WebContextMenuProxy> createContextMenuProxy(WebPageProxy*); #if ENABLE(INPUT_TYPE_COLOR) - virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& initialColor); + virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& initialColor, const WebCore::IntRect&); #endif virtual void setFindIndicator(PassRefPtr<FindIndicator>, bool, bool); @@ -115,7 +114,6 @@ private: virtual void didChangeContentsSize(const WebCore::IntSize&); private: - RefPtr<WebPageProxy> m_page; Evas_Object* m_viewWidget; }; diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_back_forward_list.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_back_forward_list.cpp index acf8d5645..f6bd0a760 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_back_forward_list.cpp +++ b/Source/WebKit2/UIProcess/API/efl/ewk_back_forward_list.cpp @@ -84,6 +84,24 @@ static inline Ewk_Back_Forward_List_Item* addItemToWrapperCache(const Ewk_Back_F return item; } +static inline Eina_List* createEinaList(const Ewk_Back_Forward_List* list, WKArrayRef wkList) +{ + if (!wkList) + return 0; + + Eina_List* result = 0; + + const size_t count = WKArrayGetSize(wkList); + for (size_t i = 0; i < count; ++i) { + WKBackForwardListItemRef wkItem = static_cast<WKBackForwardListItemRef>(WKArrayGetItemAtIndex(wkList, i)); + Ewk_Back_Forward_List_Item* item = addItemToWrapperCache(list, wkItem); + ewk_back_forward_list_item_ref(item); + result = eina_list_append(result, item); + } + + return result; +} + Ewk_Back_Forward_List_Item* ewk_back_forward_list_current_item_get(const Ewk_Back_Forward_List* list) { EWK_BACK_FORWARD_LIST_WK_GET_OR_RETURN(list, wkList, 0); @@ -121,6 +139,29 @@ unsigned ewk_back_forward_list_count(Ewk_Back_Forward_List* list) return WKBackForwardListGetBackListCount(wkList) + WKBackForwardListGetForwardListCount(wkList) + currentItem; } +Eina_List* ewk_back_forward_list_n_back_items_copy(const Ewk_Back_Forward_List* list, int limit) +{ + EWK_BACK_FORWARD_LIST_WK_GET_OR_RETURN(list, wkList, 0); + + if (limit == -1) + limit = WKBackForwardListGetBackListCount(wkList); + EINA_SAFETY_ON_FALSE_RETURN_VAL(limit >= 0, 0); + WKRetainPtr<WKArrayRef> backList(AdoptWK, WKBackForwardListCopyBackListWithLimit(wkList, limit)); + + return createEinaList(list, backList.get()); +} + +Eina_List* ewk_back_forward_list_n_forward_items_copy(const Ewk_Back_Forward_List* list, int limit) +{ + EWK_BACK_FORWARD_LIST_WK_GET_OR_RETURN(list, wkList, 0); + + if (limit == -1) + limit = WKBackForwardListGetForwardListCount(wkList); + EINA_SAFETY_ON_FALSE_RETURN_VAL(limit >= 0, 0); + WKRetainPtr<WKArrayRef> forwardList(AdoptWK, WKBackForwardListCopyForwardListWithLimit(wkList, limit)); + + return createEinaList(list, forwardList.get()); +} /** * @internal diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_back_forward_list.h b/Source/WebKit2/UIProcess/API/efl/ewk_back_forward_list.h index 5b9cca726..c58476140 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_back_forward_list.h +++ b/Source/WebKit2/UIProcess/API/efl/ewk_back_forward_list.h @@ -86,6 +86,68 @@ EAPI Ewk_Back_Forward_List_Item *ewk_back_forward_list_item_at_index_get(const E */ EAPI unsigned ewk_back_forward_list_count(Ewk_Back_Forward_List *list); +/** + * Creates the list containing the items preceding the current item limited by @a limit. + * + * The @c Ewk_Back_Forward_List_Item elements are located in the result list starting with the oldest one. + * if @a limit is equal to @c -1 all the items preceding the current item are returned. + * + * @param list the back-forward list instance + * @param limit the number of items to retrieve + * + * @return @c Eina_List containing @c Ewk_Back_Forward_List_Item elements or @c NULL in case of error, + * the Eina_List and its items should be freed after use. Use ewk_back_forward_list_item_unref() + * to free the items + */ +EAPI Eina_List *ewk_back_forward_list_n_back_items_copy(const Ewk_Back_Forward_List *list, int limit); + +/** + * Creates the list containing the items following the current item limited by @a limit. + * + * The @c Ewk_Back_Forward_List_Item elements are located in the result list starting with the oldest one. + * if @a limit is equal to @c -1 all the items preceding the current item are returned. + * + * @param list the back-forward list instance + * @param limit the number of items to retrieve + * + * @return @c Eina_List containing @c Ewk_Back_Forward_List_Item elements or @c NULL in case of error, + * the Eina_List and its items should be freed after use. Use ewk_back_forward_list_item_unref() + * to free the items + */ +EAPI Eina_List *ewk_back_forward_list_n_forward_items_copy(const Ewk_Back_Forward_List *list, int limit); + +/** + * Creates the list containing the items preceding the current item. + * + * The @c Ewk_Back_Forward_List_Item elements are located in the result list starting with the oldest one. + * + * @param list the back-forward list instance + * + * @return @c Eina_List containing @c Ewk_Back_Forward_List_Item elements or @c NULL in case of error, + * the Eina_List and its items should be freed after use. Use ewk_back_forward_list_item_unref() + * to free the items + * + * @see ewk_back_forward_list_n_back_items_copy + */ +#define ewk_back_forward_list_back_items_copy(list) \ + ewk_back_forward_list_n_back_items_copy(list, -1) + +/** + * Creates the list containing the items following the current item. + * + * The @c Ewk_Back_Forward_List_Item elements are located in the result list starting with the oldest one. + * + * @param list the back-forward list instance + * + * @return @c Eina_List containing @c Ewk_Back_Forward_List_Item elements or @c NULL in case of error, + * the Eina_List and its items should be freed after use. Use ewk_back_forward_list_item_unref() + * to free the items + * + * @see ewk_back_forward_list_n_forward_items_copy + */ +#define ewk_back_forward_list_forward_items_copy(list) \ + ewk_back_forward_list_n_forward_items_copy(list, -1) + #ifdef __cplusplus } #endif diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_context.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_context.cpp index 71504f641..60c79e16e 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_context.cpp +++ b/Source/WebKit2/UIProcess/API/efl/ewk_context.cpp @@ -25,6 +25,7 @@ #include "VibrationProvider.h" #include "WKAPICast.h" #include "WKContextSoup.h" +#include "WKNumber.h" #include "WKRetainPtr.h" #include "WKString.h" #include "ewk_context_download_client_private.h" @@ -85,6 +86,16 @@ struct _Ewk_Context { vibrationProvider = VibrationProvider::create(wkVibrationRef); #endif +#if ENABLE(MEMORY_SAMPLER) + static bool initializeMemorySampler = false; + static const char environmentVariable[] = "SAMPLE_MEMORY"; + + if (!initializeMemorySampler && getenv(environmentVariable)) { + WKRetainPtr<WKDoubleRef> interval(AdoptWK, WKDoubleCreate(0.0)); + WKContextStartMemorySampler(context.get(), interval.get()); + initializeMemorySampler = true; + } +#endif ewk_context_request_manager_client_attach(this); ewk_context_download_client_attach(this); } diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_popup_menu_item.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_popup_menu_item.cpp new file mode 100644 index 000000000..566bbef89 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_popup_menu_item.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT HOLDER OR + * 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_popup_menu_item.h" + +#include "WKEinaSharedString.h" +#include "ewk_popup_menu_item_private.h" +#include "ewk_private.h" +#include <wtf/text/CString.h> + +using namespace WebKit; + +/** + * \struct _Ewk_Popup_Menu_Item + * @brief Contains the popup menu data. + */ +struct _Ewk_Popup_Menu_Item { + Ewk_Popup_Menu_Item_Type type; + Ewk_Text_Direction textDirection; + + bool hasTextDirectionOverride; + bool isEnabled; + bool isLabel; + bool isSelected; + + WKEinaSharedString text; + WKEinaSharedString toolTip; + WKEinaSharedString accessibilityText; + + explicit _Ewk_Popup_Menu_Item(const WebKit::WebPopupItem& item) + : type(static_cast<Ewk_Popup_Menu_Item_Type>(item.m_type)) + , textDirection(static_cast<Ewk_Text_Direction>(item.m_textDirection)) + , hasTextDirectionOverride(item.m_hasTextDirectionOverride) + , isEnabled(item.m_isEnabled) + , isLabel(item.m_isLabel) + , isSelected(item.m_isSelected) + , text(item.m_text.utf8().data()) + , toolTip(item.m_toolTip.utf8().data()) + , accessibilityText(item.m_accessibilityText.utf8().data()) + { } +}; + +COMPILE_ASSERT_MATCHING_ENUM(EWK_POPUP_MENU_SEPARATOR, WebPopupItem::Separator); +COMPILE_ASSERT_MATCHING_ENUM(EWK_POPUP_MENU_ITEM, WebPopupItem::Item); + +/** + * @internal + * Constructs a Ewk_Popup_Menu_Item. + */ +Ewk_Popup_Menu_Item* ewk_popup_menu_item_new(const WebKit::WebPopupItem& item) +{ + return new Ewk_Popup_Menu_Item(item); +} + +/** + * @internal + * Frees a Ewk_Popup_Menu_Item. + */ +void ewk_popup_menu_item_free(Ewk_Popup_Menu_Item* item) +{ + EINA_SAFETY_ON_NULL_RETURN(item); + delete item; +} + +Ewk_Popup_Menu_Item_Type ewk_popup_menu_item_type_get(const Ewk_Popup_Menu_Item* item) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(item, EWK_POPUP_MENU_UNKNOWN); + + return item->type; +} + +const char* ewk_popup_menu_item_text_get(const Ewk_Popup_Menu_Item* item) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(item, 0); + + return item->text; +} + +Ewk_Text_Direction ewk_popup_menu_item_text_direction_get(const Ewk_Popup_Menu_Item* item) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(item, EWK_TEXT_DIRECTION_LEFT_TO_RIGHT); + + return item->textDirection; +} + +Eina_Bool ewk_popup_menu_item_text_direction_override_get(const Ewk_Popup_Menu_Item* item) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(item, false); + + return item->hasTextDirectionOverride; +} + +const char* ewk_popup_menu_item_tooltip_get(const Ewk_Popup_Menu_Item* item) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(item, 0); + + return item->toolTip; +} + +const char* ewk_popup_menu_item_accessibility_text_get(const Ewk_Popup_Menu_Item* item) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(item, 0); + + return item->accessibilityText; +} + +Eina_Bool ewk_popup_menu_item_enabled_get(const Ewk_Popup_Menu_Item* item) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(item, false); + + return item->isEnabled; +} + +Eina_Bool ewk_popup_menu_item_is_label_get(const Ewk_Popup_Menu_Item* item) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(item, false); + + return item->isLabel; +} + +Eina_Bool ewk_popup_menu_item_selected_get(const Ewk_Popup_Menu_Item* item) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(item, false); + + return item->isSelected; +} diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_popup_menu_item.h b/Source/WebKit2/UIProcess/API/efl/ewk_popup_menu_item.h new file mode 100644 index 000000000..b96d4366d --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_popup_menu_item.h @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT HOLDER OR + * 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_popup_menu_item.h + * @brief Describes the Ewk Popup Menu Item API. + */ + +#ifndef ewk_popup_menu_item_h +#define ewk_popup_menu_item_h + +#include "ewk_view.h" +#include <Eina.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** Enum values containing type of popup menu item. */ +typedef enum { + EWK_POPUP_MENU_SEPARATOR, + EWK_POPUP_MENU_ITEM, + EWK_POPUP_MENU_UNKNOWN = -1 +} Ewk_Popup_Menu_Item_Type; + +/** Creates a type name for _Ewk_Popup_Menu_Item */ +typedef struct _Ewk_Popup_Menu_Item Ewk_Popup_Menu_Item; + +/** + * Returns type of the popup menu item. + * + * @param item the popup menu item instance + * + * @return the type of the @a item or @c EWK_POPUP_MENU_UNKNOWN in case of error. + */ +EAPI Ewk_Popup_Menu_Item_Type ewk_popup_menu_item_type_get(const Ewk_Popup_Menu_Item *item); + +/** + * Returns text of the popup menu item. + * + * @param item the popup menu item instance + * + * @return the text of the @a item or @c NULL in case of error. 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_popup_menu_item_text_get(const Ewk_Popup_Menu_Item *item); + +/** + * Returns text direction of the popup menu item. + * + * @param item the popup menu item instance + * + * @return the text direction of the @a item. + */ +EAPI Ewk_Text_Direction ewk_popup_menu_item_text_direction_get(const Ewk_Popup_Menu_Item *item); + +/** + * Returns whether the popup menu item has text direction override. + * + * @param item the popup menu item instance + * + * @return @c EINA_TRUE if the popup menu item has text direction override, + * @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool ewk_popup_menu_item_text_direction_override_get(const Ewk_Popup_Menu_Item *item); + +/** + * Returns tooltip of the popup menu item. + * + * @param item the popup menu item instance + * + * @return the tooltip of the @a item or @c NULL in case of error. 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_popup_menu_item_tooltip_get(const Ewk_Popup_Menu_Item *item); + +/** + * Returns accessibility text of the popup menu item. + * + * @param item the popup menu item instance + * + * @return the accessibility text of the @a item or @c NULL in case of error. + * 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_popup_menu_item_accessibility_text_get(const Ewk_Popup_Menu_Item *item); + +/** + * Returns whether the popup menu item is enabled or not. + * + * @param item the popup menu item instance + * + * @return @c EINA_TRUE if ther popup menu item is enabled, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool ewk_popup_menu_item_enabled_get(const Ewk_Popup_Menu_Item *item); + +/** + * Returns whether the popup menu item is label or not. + * + * @param item the popup menu item instance + * + * @return @c EINA_TRUE if the popup menu item is label, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool ewk_popup_menu_item_is_label_get(const Ewk_Popup_Menu_Item *item); + +/** + * Returns whether the popup menu item is selected or not. + * + * @param item the popup menu item instance + * + * @return @c EINA_TRUE if the popup menu item is selected, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool ewk_popup_menu_item_selected_get(const Ewk_Popup_Menu_Item *item); + +#ifdef __cplusplus +} +#endif +#endif // ewk_popup_menu_item_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_popup_menu_item_private.h b/Source/WebKit2/UIProcess/API/efl/ewk_popup_menu_item_private.h new file mode 100644 index 000000000..6a4a435bf --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_popup_menu_item_private.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT HOLDER OR + * 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_popup_menu_item_private_h +#define ewk_popup_menu_item_private_h + +#include "WebPopupItem.h" + +Ewk_Popup_Menu_Item* ewk_popup_menu_item_new(const WebKit::WebPopupItem& item); +void ewk_popup_menu_item_free(Ewk_Popup_Menu_Item* item); + +#endif // ewk_popup_menu_item_private_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_settings.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_settings.cpp new file mode 100644 index 000000000..9055ce7eb --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_settings.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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_settings.h" + +#include "ewk_settings_private.h" +#include <WebKit2/WKPreferences.h> + +using namespace WebKit; + +Eina_Bool ewk_settings_fullscreen_enabled_set(Ewk_Settings* settings, Eina_Bool enable) +{ +#if ENABLE(FULLSCREEN_API) + EINA_SAFETY_ON_NULL_RETURN_VAL(settings, false); + WKPreferencesSetFullScreenEnabled(settings->preferences.get(), enable); + return true; +#else + return false; +#endif +} + +Eina_Bool ewk_settings_fullscreen_enabled_get(const Ewk_Settings* settings) +{ +#if ENABLE(FULLSCREEN_API) + EINA_SAFETY_ON_NULL_RETURN_VAL(settings, false); + return WKPreferencesGetFullScreenEnabled(settings->preferences.get()); +#else + return false; +#endif +} + +Eina_Bool ewk_settings_javascript_enabled_set(Ewk_Settings* settings, Eina_Bool enable) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(settings, false); + + WKPreferencesSetJavaScriptEnabled(settings->preferences.get(), enable); + + return true; +} + +Eina_Bool ewk_settings_javascript_enabled_get(const Ewk_Settings* settings) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(settings, false); + + return WKPreferencesGetJavaScriptEnabled(settings->preferences.get()); +} + +Eina_Bool ewk_settings_loads_images_automatically_set(Ewk_Settings* settings, Eina_Bool automatic) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(settings, false); + + WKPreferencesSetLoadsImagesAutomatically(settings->preferences.get(), automatic); + + return true; +} + +Eina_Bool ewk_settings_loads_images_automatically_get(const Ewk_Settings* settings) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(settings, false); + + return WKPreferencesGetLoadsImagesAutomatically(settings->preferences.get()); +} diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_settings.h b/Source/WebKit2/UIProcess/API/efl/ewk_settings.h new file mode 100644 index 000000000..a28d40be2 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_settings.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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_settings.h + * @brief Describes the settings API. + * + * @note The ewk_settings is for setting the preference of specific ewk_view. + * We can get the ewk_settings from ewk_view using ewk_view_settings_get() API. + */ + +#ifndef ewk_settings_h +#define ewk_settings_h + +#include <Eina.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** Creates a type name for _Ewk_Settings */ +typedef struct _Ewk_Settings Ewk_Settings; + +/** + * Enables/disables the Javascript Fullscreen API. The Javascript API allows + * to request full screen mode, for more information see: + * http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html + * + * Default value for Javascript Fullscreen API setting is @c EINA_TRUE . + * + * @param settings settings object to enable Javascript Fullscreen API + * @param enable @c EINA_TRUE to enable Javascript Fullscreen API or + * @c EINA_FALSE to disable + * + * @return @c EINA_TRUE on success or @c EINA_FALSE on failure + */ +EAPI Eina_Bool ewk_settings_fullscreen_enabled_set(Ewk_Settings *settings, Eina_Bool enable); + +/** + * Returns whether the Javascript Fullscreen API is enabled or not. + * + * @param settings settings object to query whether Javascript Fullscreen API is enabled + * + * @return @c EINA_TRUE if the Javascript Fullscreen API is enabled + * @c EINA_FALSE if not or on failure + */ +EAPI Eina_Bool ewk_settings_fullscreen_enabled_get(const Ewk_Settings *settings); + +/** + * Enables/disables the javascript executing. + * + * @param settings settings object to set javascript executing + * @param enable @c EINA_TRUE to enable javascript executing + * @c EINA_FALSE to disable + * + * @return @c EINA_TRUE on success or @c EINA_FALSE on failure + */ +EAPI Eina_Bool ewk_settings_javascript_enabled_set(Ewk_Settings *settings, Eina_Bool enable); + +/** + * Returns the javascript can be executable or not. + * + * @param settings settings object to query if the javascript can be executed + * + * @return @c EINA_TRUE if the javascript can be executed + * @c EINA_FALSE if not or on failure + */ +EAPI Eina_Bool ewk_settings_javascript_enabled_get(const Ewk_Settings *settings); + +/** + * Enables/disables auto loading of the images. + * + * @param settings settings object to set auto loading of the images + * @param automatic @c EINA_TRUE to enable auto loading of the images, + * @c EINA_FALSE to disable + * + * @return @c EINA_TRUE on success or @c EINA_FALSE on failure + */ +EAPI Eina_Bool ewk_settings_loads_images_automatically_set(Ewk_Settings *settings, Eina_Bool automatic); + +/** + * Returns the images can be loaded automatically or not. + * + * @param settings settings object to get auto loading of the images + * + * @return @c EINA_TRUE if the images are loaded automatically, + * @c EINA_FALSE if not or on failure + */ +EAPI Eina_Bool ewk_settings_loads_images_automatically_get(const Ewk_Settings *settings); + +#ifdef __cplusplus +} +#endif +#endif // ewk_settings_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_settings_private.h b/Source/WebKit2/UIProcess/API/efl/ewk_settings_private.h new file mode 100644 index 000000000..2c9da0d7c --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_settings_private.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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_settings_private_h +#define ewk_settings_private_h + +#include "ewk_settings.h" +#include <WebKit2/WKPreferences.h> +#include <WebKit2/WKRetainPtr.h> +#include <wtf/PassOwnPtr.h> + +/** Creates a type name for _Ewk_Settings */ +typedef struct _Ewk_Settings Ewk_Settings; + +/** + * \struct _Ewk_Settings + * @brief Contains the settings data. + */ +struct _Ewk_Settings { + WKRetainPtr<WKPreferencesRef> preferences; + + explicit _Ewk_Settings(WKPreferencesRef wkPreferences) + : preferences(wkPreferences) + { } +}; + +#endif // ewk_settings_private_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp index ce7f7b454..9971b1634 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp +++ b/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp @@ -31,11 +31,19 @@ #include "WKRetainPtr.h" #include "WKString.h" #include "WKURL.h" +#include "WebContext.h" +#include "WebPageGroup.h" +#include "WebPopupItem.h" +#include "WebPopupMenuProxyEfl.h" +#include "WebPreferences.h" #include "ewk_back_forward_list_private.h" #include "ewk_context.h" #include "ewk_context_private.h" #include "ewk_intent_private.h" +#include "ewk_popup_menu_item.h" +#include "ewk_popup_menu_item_private.h" #include "ewk_private.h" +#include "ewk_settings_private.h" #include "ewk_view_find_client_private.h" #include "ewk_view_form_client_private.h" #include "ewk_view_loader_client_private.h" @@ -48,8 +56,13 @@ #include <Edje.h> #include <WebCore/Cursor.h> #include <WebCore/EflScreenUtilities.h> +#include <WebKit2/WKPageGroup.h> #include <wtf/text/CString.h> +#if ENABLE(FULLSCREEN_API) +#include "WebFullScreenManagerProxy.h" +#endif + #if USE(ACCELERATED_COMPOSITING) #include <Evas_GL.h> #endif @@ -73,6 +86,7 @@ struct _Ewk_View_Private_Data { #if USE(COORDINATED_GRAPHICS) OwnPtr<EflViewportHandler> viewportHandler; #endif + RefPtr<WebPageProxy> pageProxy; WKEinaSharedString uri; WKEinaSharedString title; @@ -82,6 +96,11 @@ struct _Ewk_View_Private_Data { Evas_Object* cursorObject; LoadingResourcesMap loadingResourcesMap; Ewk_Back_Forward_List* backForwardList; + OwnPtr<Ewk_Settings> settings; + bool areMouseEventsEnabled; + + WebPopupMenuProxyEfl* popupMenuProxy; + Eina_List* popupMenuItems; #ifdef HAVE_ECORE_X bool isUsingEcoreX; @@ -96,6 +115,9 @@ struct _Ewk_View_Private_Data { _Ewk_View_Private_Data() : cursorObject(0) , backForwardList(0) + , areMouseEventsEnabled(false) + , popupMenuProxy(0) + , popupMenuItems(0) #ifdef HAVE_ECORE_X , isUsingEcoreX(false) #endif @@ -114,6 +136,10 @@ struct _Ewk_View_Private_Data { evas_object_del(cursorObject); ewk_back_forward_list_free(backForwardList); + + void* item; + EINA_LIST_FREE(popupMenuItems, item) + ewk_popup_menu_item_free(static_cast<Ewk_Popup_Menu_Item*>(item)); } }; @@ -148,15 +174,17 @@ struct _Ewk_View_Private_Data { EWK_VIEW_TYPE_CHECK(ewkView, _tmp_result); \ Ewk_View_Smart_Data* smartData = 0; \ if (_tmp_result) \ - smartData = (Ewk_View_Smart_Data*)evas_object_smart_data_get(ewkView); + smartData = (Ewk_View_Smart_Data*)evas_object_smart_data_get(ewkView) #define EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, ...) \ EWK_VIEW_SD_GET(ewkView, smartData); \ - if (!smartData) { \ - EINA_LOG_CRIT("no smart data for object %p (%s)", \ - ewkView, evas_object_type_get(ewkView)); \ - return __VA_ARGS__; \ - } + do { \ + if (!smartData) { \ + EINA_LOG_CRIT("no smart data for object %p (%s)", \ + ewkView, evas_object_type_get(ewkView)); \ + return __VA_ARGS__; \ + } \ + } while (0) #define EWK_VIEW_PRIV_GET(smartData, priv) \ Ewk_View_Private_Data* priv = smartData->priv @@ -167,11 +195,13 @@ struct _Ewk_View_Private_Data { return __VA_ARGS__; \ } \ EWK_VIEW_PRIV_GET(smartData, priv); \ - if (!priv) { \ - EINA_LOG_CRIT("no private data for object %p (%s)", \ - smartData->self, evas_object_type_get(smartData->self)); \ - return __VA_ARGS__; \ - } + do { \ + if (!priv) { \ + EINA_LOG_CRIT("no private data for object %p (%s)", \ + smartData->self, evas_object_type_get(smartData->self)); \ + return __VA_ARGS__; \ + } \ + } while (0) static void _ewk_view_smart_changed(Ewk_View_Smart_Data* smartData) { @@ -184,69 +214,69 @@ static void _ewk_view_smart_changed(Ewk_View_Smart_Data* smartData) // Default Event Handling. static Eina_Bool _ewk_view_smart_focus_in(Ewk_View_Smart_Data* smartData) { - EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false) + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - priv->pageClient->page()->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive); + priv->pageProxy->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive); return true; } static Eina_Bool _ewk_view_smart_focus_out(Ewk_View_Smart_Data* smartData) { - EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false) + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - priv->pageClient->page()->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive); + priv->pageProxy->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive); return true; } static Eina_Bool _ewk_view_smart_mouse_wheel(Ewk_View_Smart_Data* smartData, const Evas_Event_Mouse_Wheel* wheelEvent) { - EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false) + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); Evas_Point position = {smartData->view.x, smartData->view.y}; - priv->pageClient->page()->handleWheelEvent(NativeWebWheelEvent(wheelEvent, &position)); + priv->pageProxy->handleWheelEvent(NativeWebWheelEvent(wheelEvent, &position)); return true; } static Eina_Bool _ewk_view_smart_mouse_down(Ewk_View_Smart_Data* smartData, const Evas_Event_Mouse_Down* downEvent) { - EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false) + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); Evas_Point position = {smartData->view.x, smartData->view.y}; - priv->pageClient->page()->handleMouseEvent(NativeWebMouseEvent(downEvent, &position)); + priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(downEvent, &position)); return true; } static Eina_Bool _ewk_view_smart_mouse_up(Ewk_View_Smart_Data* smartData, const Evas_Event_Mouse_Up* upEvent) { - EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false) + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); Evas_Point position = {smartData->view.x, smartData->view.y}; - priv->pageClient->page()->handleMouseEvent(NativeWebMouseEvent(upEvent, &position)); + priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(upEvent, &position)); return true; } static Eina_Bool _ewk_view_smart_mouse_move(Ewk_View_Smart_Data* smartData, const Evas_Event_Mouse_Move* moveEvent) { - EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false) + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); Evas_Point position = {smartData->view.x, smartData->view.y}; - priv->pageClient->page()->handleMouseEvent(NativeWebMouseEvent(moveEvent, &position)); + priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(moveEvent, &position)); return true; } static Eina_Bool _ewk_view_smart_key_down(Ewk_View_Smart_Data* smartData, const Evas_Event_Key_Down* downEvent) { - EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false) + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - priv->pageClient->page()->handleKeyboardEvent(NativeWebKeyboardEvent(downEvent)); + priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(downEvent)); return true; } static Eina_Bool _ewk_view_smart_key_up(Ewk_View_Smart_Data* smartData, const Evas_Event_Key_Up* upEvent) { - EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false) + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - priv->pageClient->page()->handleKeyboardEvent(NativeWebKeyboardEvent(upEvent)); + priv->pageProxy->handleKeyboardEvent(NativeWebKeyboardEvent(upEvent)); return true; } @@ -390,13 +420,12 @@ static void _ewk_view_smart_add(Evas_Object* ewkView) evas_object_smart_member_add(smartData->image, ewkView); evas_object_show(smartData->image); + ewk_view_mouse_events_enabled_set(ewkView, true); + #define CONNECT(s, c) evas_object_event_callback_add(ewkView, s, c, smartData) CONNECT(EVAS_CALLBACK_FOCUS_IN, _ewk_view_on_focus_in); CONNECT(EVAS_CALLBACK_FOCUS_OUT, _ewk_view_on_focus_out); CONNECT(EVAS_CALLBACK_MOUSE_WHEEL, _ewk_view_on_mouse_wheel); - CONNECT(EVAS_CALLBACK_MOUSE_DOWN, _ewk_view_on_mouse_down); - CONNECT(EVAS_CALLBACK_MOUSE_UP, _ewk_view_on_mouse_up); - CONNECT(EVAS_CALLBACK_MOUSE_MOVE, _ewk_view_on_mouse_move); CONNECT(EVAS_CALLBACK_KEY_DOWN, _ewk_view_on_key_down); CONNECT(EVAS_CALLBACK_KEY_UP, _ewk_view_on_key_up); #undef CONNECT @@ -534,8 +563,8 @@ static void _ewk_view_smart_calculate(Evas_Object* ewkView) priv->viewportHandler->updateViewportSize(IntSize(width, height)); #endif - if (priv->pageClient->page()->drawingArea()) - priv->pageClient->page()->drawingArea()->setSize(IntSize(width, height), IntSize()); + if (priv->pageProxy->drawingArea()) + priv->pageProxy->drawingArea()->setSize(IntSize(width, height), IntSize()); #if USE(ACCELERATED_COMPOSITING) if (!priv->evasGlSurface) @@ -597,8 +626,8 @@ static void _ewk_view_smart_color_set(Evas_Object* ewkView, int red, int green, #undef CHECK_COLOR evas_object_image_alpha_set(smartData->image, alpha < 255); - priv->pageClient->page()->setDrawsBackground(red || green || blue); - priv->pageClient->page()->setDrawsTransparentBackground(alpha < 255); + priv->pageProxy->setDrawsBackground(red || green || blue); + priv->pageProxy->setDrawsTransparentBackground(alpha < 255); g_parentSmartClass.color_set(ewkView, red, green, blue, alpha); } @@ -658,28 +687,43 @@ static inline Evas_Smart* _ewk_view_smart_class_new(void) static void _ewk_view_initialize(Evas_Object* ewkView, Ewk_Context* context, WKPageGroupRef pageGroupRef) { EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); - EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv) + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); EINA_SAFETY_ON_NULL_RETURN(context); if (priv->pageClient) return; - priv->pageClient = PageClientImpl::create(toImpl(ewk_context_WKContext_get(context)), toImpl(pageGroupRef), ewkView); - priv->backForwardList = ewk_back_forward_list_new(toAPI(priv->pageClient->page()->backForwardList())); + priv->pageClient = PageClientImpl::create(ewkView); + if (pageGroupRef) + priv->pageProxy = toImpl(ewk_context_WKContext_get(context))->createWebPage(priv->pageClient.get(), toImpl(pageGroupRef)); + else + priv->pageProxy = toImpl(ewk_context_WKContext_get(context))->createWebPage(priv->pageClient.get(), WebPageGroup::create().get()); #if USE(COORDINATED_GRAPHICS) - priv->viewportHandler = EflViewportHandler::create(priv->pageClient.get()); + priv->pageProxy->pageGroup()->preferences()->setAcceleratedCompositingEnabled(true); + priv->pageProxy->pageGroup()->preferences()->setForceCompositingMode(true); + priv->pageProxy->setUseFixedLayout(true); #endif + priv->pageProxy->initializeWebPage(); + + priv->backForwardList = ewk_back_forward_list_new(toAPI(priv->pageProxy->backForwardList())); + priv->settings = adoptPtr(new Ewk_Settings(WKPageGroupGetPreferences(WKPageGetPageGroup(toAPI(priv->pageProxy.get()))))); - WKPageRef wkPage = toAPI(priv->pageClient->page()); +#if USE(COORDINATED_GRAPHICS) + priv->viewportHandler = EflViewportHandler::create(ewkView); +#endif + + WKPageRef wkPage = toAPI(priv->pageProxy.get()); ewk_view_find_client_attach(wkPage, ewkView); 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_ui_client_attach(wkPage, ewkView); - - ewk_view_theme_set(ewkView, DEFAULT_THEME_PATH"/default.edj"); +#if ENABLE(FULLSCREEN_API) + priv->pageProxy->fullScreenManager()->setWebView(ewkView); + ewk_settings_fullscreen_enabled_set(priv->settings.get(), true); +#endif } static Evas_Object* _ewk_view_add_with_smart(Evas* canvas, Evas_Smart* smart) @@ -759,7 +803,7 @@ void ewk_view_uri_update(Evas_Object* ewkView) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); - String activeURL = priv->pageClient->page()->activeURL(); + String activeURL = priv->pageProxy->activeURL(); if (activeURL.isEmpty()) return; @@ -777,7 +821,7 @@ Eina_Bool ewk_view_uri_set(Evas_Object* ewkView, const char* uri) EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); EINA_SAFETY_ON_NULL_RETURN_VAL(uri, false); - priv->pageClient->page()->loadURL(uri); + priv->pageProxy->loadURL(uri); ewk_view_uri_update(ewkView); return true; @@ -796,7 +840,7 @@ 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); - priv->pageClient->page()->reload(/*reloadFromOrigin*/ false); + priv->pageProxy->reload(/*reloadFromOrigin*/ false); ewk_view_uri_update(ewkView); return true; @@ -807,7 +851,7 @@ 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); - priv->pageClient->page()->reload(/*reloadFromOrigin*/ true); + priv->pageProxy->reload(/*reloadFromOrigin*/ true); ewk_view_uri_update(ewkView); return true; @@ -818,11 +862,19 @@ 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); - priv->pageClient->page()->stopLoading(); + priv->pageProxy->stopLoading(); return true; } +Ewk_Settings* ewk_view_settings_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->settings.get(); +} + /** * @internal * Load was initiated for a resource in the view. @@ -926,7 +978,7 @@ const char* ewk_view_title_get(const Evas_Object* ewkView) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0); - CString title = priv->pageClient->page()->pageTitle().utf8(); + CString title = priv->pageProxy->pageTitle().utf8(); priv->title = title.data(); return priv->title; @@ -959,7 +1011,7 @@ double ewk_view_load_progress_get(const Evas_Object* ewkView) 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(); + return priv->pageProxy->estimatedProgress(); } Eina_Bool ewk_view_scale_set(Evas_Object* ewkView, double scaleFactor, int x, int y) @@ -967,7 +1019,7 @@ Eina_Bool ewk_view_scale_set(Evas_Object* ewkView, double scaleFactor, int x, in 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)); + priv->pageProxy->scalePage(scaleFactor, IntPoint(x, y)); return true; } @@ -976,7 +1028,7 @@ 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 priv->pageClient->page()->pageScaleFactor(); + return priv->pageProxy->pageScaleFactor(); } Eina_Bool ewk_view_device_pixel_ratio_set(Evas_Object* ewkView, float ratio) @@ -984,7 +1036,7 @@ Eina_Bool ewk_view_device_pixel_ratio_set(Evas_Object* ewkView, float ratio) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - priv->pageClient->page()->setCustomDeviceScaleFactor(ratio); + priv->pageProxy->setCustomDeviceScaleFactor(ratio); return true; } @@ -994,7 +1046,7 @@ float ewk_view_device_pixel_ratio_get(const Evas_Object* ewkView) 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(); + return priv->pageProxy->deviceScaleFactor(); } /** @@ -1028,7 +1080,7 @@ void ewk_view_theme_set(Evas_Object* ewkView, const char* path) if (priv->theme != path) { priv->theme = path; - priv->pageClient->page()->setThemePath(path); + priv->pageProxy->setThemePath(path); } } @@ -1108,6 +1160,37 @@ 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()); } +#if ENABLE(FULLSCREEN_API) +/** + * @internal + * Calls fullscreen_enter callback or falls back to default behavior and enables fullscreen mode. + */ +void ewk_view_full_screen_enter(Evas_Object* ewkView) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); + + if (!smartData->api->fullscreen_enter || !smartData->api->fullscreen_enter(smartData)) { + Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(smartData->base.evas); + ecore_evas_fullscreen_set(ecoreEvas, true); + } +} + +/** + * @internal + * Calls fullscreen_exit callback or falls back to default behavior and disables fullscreen mode. + */ +void ewk_view_full_screen_exit(Evas_Object* ewkView) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); + + if (!smartData->api->fullscreen_exit || !smartData->api->fullscreen_exit(smartData)) { + Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(smartData->base.evas); + ecore_evas_fullscreen_set(ecoreEvas, false); + } +} +#endif + + /** * @internal * A download for that view was cancelled. @@ -1158,7 +1241,7 @@ 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); - WebPageProxy* page = priv->pageClient->page(); + WebPageProxy* page = priv->pageProxy.get(); if (page->canGoBack()) { page->goBack(); return true; @@ -1172,7 +1255,7 @@ 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); - WebPageProxy* page = priv->pageClient->page(); + WebPageProxy* page = priv->pageProxy.get(); if (page->canGoForward()) { page->goForward(); return true; @@ -1188,7 +1271,7 @@ 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); - WebPageProxy* page = priv->pageClient->page(); + WebPageProxy* page = priv->pageProxy.get(); page->deliverIntentToFrame(page->mainFrame(), toImpl(ewk_intent_WKIntentDataRef_get(intent))); return true; @@ -1202,7 +1285,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 priv->pageClient->page()->canGoBack(); + return priv->pageProxy->canGoBack(); } Eina_Bool ewk_view_forward_possible(Evas_Object* ewkView) @@ -1210,7 +1293,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 priv->pageClient->page()->canGoForward(); + return priv->pageProxy->canGoForward(); } Ewk_Back_Forward_List* ewk_view_back_forward_list_get(const Evas_Object* ewkView) @@ -1337,9 +1420,9 @@ Eina_Bool ewk_view_html_string_load(Evas_Object* ewkView, const char* html, cons EINA_SAFETY_ON_NULL_RETURN_VAL(html, false); if (unreachableUrl && *unreachableUrl) - priv->pageClient->page()->loadAlternateHTMLString(String::fromUTF8(html), baseUrl ? String::fromUTF8(baseUrl) : "", String::fromUTF8(unreachableUrl)); + priv->pageProxy->loadAlternateHTMLString(String::fromUTF8(html), baseUrl ? String::fromUTF8(baseUrl) : "", String::fromUTF8(unreachableUrl)); else - priv->pageClient->page()->loadHTMLString(String::fromUTF8(html), baseUrl ? String::fromUTF8(baseUrl) : ""); + priv->pageProxy->loadHTMLString(String::fromUTF8(html), baseUrl ? String::fromUTF8(baseUrl) : ""); ewk_view_uri_update(ewkView); return true; @@ -1363,7 +1446,7 @@ WebPageProxy* ewk_view_page_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->pageClient->page(); + return priv->pageProxy.get(); } const char* ewk_view_setting_encoding_custom_get(const Evas_Object* ewkView) @@ -1371,7 +1454,7 @@ 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); - String customEncoding = priv->pageClient->page()->customTextEncodingName(); + String customEncoding = priv->pageProxy->customTextEncodingName(); if (customEncoding.isEmpty()) return 0; @@ -1386,7 +1469,7 @@ Eina_Bool ewk_view_setting_encoding_custom_set(Evas_Object* ewkView, const char* EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); priv->customEncoding = encoding; - priv->pageClient->page()->setCustomTextEncodingName(encoding ? encoding : String()); + priv->pageProxy->setCustomTextEncodingName(encoding ? encoding : String()); return true; } @@ -1424,7 +1507,7 @@ Eina_Bool ewk_view_text_find(Evas_Object* ewkView, const char* text, Ewk_Find_Op EINA_SAFETY_ON_NULL_RETURN_VAL(text, false); WKRetainPtr<WKStringRef> findText(AdoptWK, WKStringCreateWithUTF8CString(text)); - WKPageFindString(toAPI(priv->pageClient->page()), findText.get(), static_cast<WKFindOptions>(options), maxMatchCount); + WKPageFindString(toAPI(priv->pageProxy.get()), findText.get(), static_cast<WKFindOptions>(options), maxMatchCount); return true; } @@ -1434,7 +1517,7 @@ Eina_Bool ewk_view_text_find_highlight_clear(Evas_Object* ewkView) EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); - WKPageHideFindUI(toAPI(priv->pageClient->page())); + WKPageHideFindUI(toAPI(priv->pageProxy.get())); return true; } @@ -1448,3 +1531,96 @@ void ewk_view_contents_size_changed(const Evas_Object* ewkView, const IntSize& s priv->viewportHandler->didChangeContentsSize(size); #endif } + +COMPILE_ASSERT_MATCHING_ENUM(EWK_TEXT_DIRECTION_RIGHT_TO_LEFT, RTL); +COMPILE_ASSERT_MATCHING_ENUM(EWK_TEXT_DIRECTION_LEFT_TO_RIGHT, LTR); + +void ewk_view_popup_menu_request(Evas_Object* ewkView, WebPopupMenuProxyEfl* popupMenu, const IntRect& rect, TextDirection textDirection, double pageScaleFactor, const Vector<WebPopupItem>& items, int32_t selectedIndex) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); + EINA_SAFETY_ON_NULL_RETURN(smartData->api); + + ASSERT(popupMenu); + + if (!smartData->api->popup_menu_show) + return; + + if (priv->popupMenuProxy) + ewk_view_popup_menu_close(ewkView); + priv->popupMenuProxy = popupMenu; + + Eina_List* popupItems = 0; + size_t size = items.size(); + for (size_t i = 0; i < size; ++i) + popupItems = eina_list_append(popupItems, ewk_popup_menu_item_new(items[i])); + priv->popupMenuItems = popupItems; + + smartData->api->popup_menu_show(smartData, rect, static_cast<Ewk_Text_Direction>(textDirection), pageScaleFactor, popupItems, selectedIndex); +} + +Eina_Bool ewk_view_popup_menu_close(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(smartData->api, false); + + if (!priv->popupMenuProxy) + return false; + + priv->popupMenuProxy = 0; + + if (smartData->api->popup_menu_hide) + smartData->api->popup_menu_hide(smartData); + + void* item; + EINA_LIST_FREE(priv->popupMenuItems, item) + ewk_popup_menu_item_free(static_cast<Ewk_Popup_Menu_Item*>(item)); + + return true; +} + +Eina_Bool ewk_view_popup_menu_select(Evas_Object* ewkView, unsigned int selectedIndex) +{ + 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->popupMenuProxy, false); + + if (selectedIndex >= eina_list_count(priv->popupMenuItems)) + return false; + + priv->popupMenuProxy->valueChanged(selectedIndex); + + return true; +} + +Eina_Bool ewk_view_mouse_events_enabled_set(Evas_Object* ewkView, Eina_Bool enabled) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); + + enabled = !!enabled; + if (priv->areMouseEventsEnabled == enabled) + return true; + + priv->areMouseEventsEnabled = enabled; + if (enabled) { + evas_object_event_callback_add(ewkView, EVAS_CALLBACK_MOUSE_DOWN, _ewk_view_on_mouse_down, smartData); + evas_object_event_callback_add(ewkView, EVAS_CALLBACK_MOUSE_UP, _ewk_view_on_mouse_up, smartData); + evas_object_event_callback_add(ewkView, EVAS_CALLBACK_MOUSE_MOVE, _ewk_view_on_mouse_move, smartData); + } else { + evas_object_event_callback_del(ewkView, EVAS_CALLBACK_MOUSE_DOWN, _ewk_view_on_mouse_down); + evas_object_event_callback_del(ewkView, EVAS_CALLBACK_MOUSE_UP, _ewk_view_on_mouse_up); + evas_object_event_callback_del(ewkView, EVAS_CALLBACK_MOUSE_MOVE, _ewk_view_on_mouse_move); + } + + return true; +} + +Eina_Bool ewk_view_mouse_events_enabled_get(const Evas_Object* ewkView) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, false); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, false); + + return priv->areMouseEventsEnabled; +} diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_view.h b/Source/WebKit2/UIProcess/API/efl/ewk_view.h index afa45846f..b040fdf30 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_view.h +++ b/Source/WebKit2/UIProcess/API/efl/ewk_view.h @@ -73,6 +73,7 @@ #include "ewk_context.h" #include "ewk_download_job.h" #include "ewk_intent.h" +#include "ewk_settings.h" #include "ewk_url_request.h" #include "ewk_url_response.h" #include "ewk_web_error.h" @@ -83,6 +84,12 @@ extern "C" { #endif +/// Enum values containing text directionality values. +typedef enum { + EWK_TEXT_DIRECTION_RIGHT_TO_LEFT, + EWK_TEXT_DIRECTION_LEFT_TO_RIGHT +} Ewk_Text_Direction; + typedef struct _Ewk_View_Smart_Data Ewk_View_Smart_Data; typedef struct _Ewk_View_Smart_Class Ewk_View_Smart_Class; @@ -91,11 +98,16 @@ struct _Ewk_View_Smart_Class { Evas_Smart_Class sc; /**< all but 'data' is free to be changed. */ unsigned long version; + Eina_Bool (*popup_menu_show)(Ewk_View_Smart_Data *sd, Eina_Rectangle rect, Ewk_Text_Direction text_direction, double page_scale_factor, Eina_List *items, int selected_index); + Eina_Bool (*popup_menu_hide)(Ewk_View_Smart_Data *sd); + // event handling: // - returns true if handled // - if overridden, have to call parent method if desired Eina_Bool (*focus_in)(Ewk_View_Smart_Data *sd); Eina_Bool (*focus_out)(Ewk_View_Smart_Data *sd); + Eina_Bool (*fullscreen_enter)(Ewk_View_Smart_Data *sd); + Eina_Bool (*fullscreen_exit)(Ewk_View_Smart_Data *sd); Eina_Bool (*mouse_wheel)(Ewk_View_Smart_Data *sd, const Evas_Event_Mouse_Wheel *ev); Eina_Bool (*mouse_down)(Ewk_View_Smart_Data *sd, const Evas_Event_Mouse_Down *ev); Eina_Bool (*mouse_up)(Ewk_View_Smart_Data *sd, const Evas_Event_Mouse_Up *ev); @@ -108,7 +120,7 @@ struct _Ewk_View_Smart_Class { * The version you have to put into the version field * in the @a Ewk_View_Smart_Class structure. */ -#define EWK_VIEW_SMART_CLASS_VERSION 1UL +#define EWK_VIEW_SMART_CLASS_VERSION 3UL /** * Initializer for whole Ewk_View_Smart_Class structure. @@ -120,7 +132,7 @@ struct _Ewk_View_Smart_Class { * @see EWK_VIEW_SMART_CLASS_INIT_VERSION * @see EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION */ -#define EWK_VIEW_SMART_CLASS_INIT(smart_class_init) {smart_class_init, EWK_VIEW_SMART_CLASS_VERSION, 0, 0, 0, 0, 0, 0, 0, 0} +#define EWK_VIEW_SMART_CLASS_INIT(smart_class_init) {smart_class_init, EWK_VIEW_SMART_CLASS_VERSION, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /** * Initializer to zero a whole Ewk_View_Smart_Class structure. @@ -347,6 +359,15 @@ EAPI Eina_Bool ewk_view_reload_bypass_cache(Evas_Object *o); EAPI Eina_Bool ewk_view_stop(Evas_Object *o); /** + * Gets the Ewk_Settings of this view. + * + * @param o view object to get Ewk_Settings + * + * @return the Ewk_Settings of this view or @c NULL on failure + */ +EAPI Ewk_Settings *ewk_view_settings_get(const Evas_Object *o); + +/** * Delivers a Web intent to the view's main frame. * * @param o view object to deliver the intent to @@ -534,7 +555,7 @@ EAPI Eina_Bool ewk_view_device_pixel_ratio_set(Evas_Object *o, float ratio); * use this one. * * @param o view object to change theme - * @param path theme path, may be @c NULL to reset to the default theme + * @param path theme path */ EAPI void ewk_view_theme_set(Evas_Object *o, const char *path); @@ -590,6 +611,49 @@ EAPI Eina_Bool ewk_view_text_find(Evas_Object *o, const char *text, Ewk_Find_Opt */ EAPI Eina_Bool ewk_view_text_find_highlight_clear(Evas_Object *o); +/** + * Selects index of current popup menu. + * + * @param o view object contains popup menu. + * @param index index of item to select + * + * @return @c EINA_TRUE on success, @c EINA_FALSE on failure (probably + * popup menu is not selected or index is out of range) + */ +EAPI Eina_Bool ewk_view_popup_menu_select(Evas_Object *o, unsigned int index); + +/** + * Closes current popup menu. + * + * @param o view object contains popup menu. + * + * @return @c EINA_TRUE on success, @c EINA_FALSE on failure (probably + * popup menu is not selected) + */ +EAPI Eina_Bool ewk_view_popup_menu_close(Evas_Object *o); + +/** + * Sets whether the ewk_view supports the mouse events or not. + * + * The ewk_view will support the mouse events if EINA_TRUE or not support the + * mouse events otherwise. The default value is EINA_TRUE. + * + * @param o view object to enable/disable the mouse events + * @param enabled a state to set + * + * @return @c EINA_TRUE on success or @c EINA_FALSE on failure + */ +EAPI Eina_Bool ewk_view_mouse_events_enabled_set(Evas_Object *o, Eina_Bool enabled); + +/** + * Queries if the ewk_view supports the mouse events. + * + * @param o view object to query if the mouse events are enabled + * + * @return @c EINA_TRUE if the mouse events are enabled or @c EINA_FALSE otherwise + */ +EAPI Eina_Bool ewk_view_mouse_events_enabled_get(const Evas_Object *o); + #ifdef __cplusplus } #endif diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_view_policy_client.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_view_policy_client.cpp index 6e2540f80..cf3b85e09 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_view_policy_client.cpp +++ b/Source/WebKit2/UIProcess/API/efl/ewk_view_policy_client.cpp @@ -31,6 +31,7 @@ #include "ewk_navigation_policy_decision_private.h" #include "ewk_view_policy_client_private.h" #include "ewk_view_private.h" +#include <WebCore/HTTPStatusCodes.h> #include <wtf/text/CString.h> using namespace WebCore; @@ -58,6 +59,13 @@ static void decidePolicyForNewWindowAction(WKPageRef page, WKFrameRef frame, WKF static void decidePolicyForResponseCallback(WKPageRef page, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo) { const ResourceResponse resourceResponse = toImpl(response)->resourceResponse(); + + // Ignore responses with an HTTP status code of 204 (No Content) + if (resourceResponse.httpStatusCode() == HTTPNoContent) { + WKFramePolicyListenerIgnore(listener); + return; + } + // If the URL Response has "Content-Disposition: attachment;" header, then // we should download it. if (resourceResponse.isAttachment()) { diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_view_private.h b/Source/WebKit2/UIProcess/API/efl/ewk_view_private.h index f40298587..fcd65ee0f 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_view_private.h +++ b/Source/WebKit2/UIProcess/API/efl/ewk_view_private.h @@ -23,7 +23,9 @@ #include "WebPageProxy.h" #include <Evas.h> +#include <WebCore/TextDirection.h> #include <WebKit2/WKBase.h> +#include <wtf/Vector.h> namespace WebCore { class Cursor; @@ -31,6 +33,11 @@ class IntRect; class IntSize; } +namespace WebKit { +class WebPopupItem; +class WebPopupMenuProxyEfl; +} + 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; @@ -52,6 +59,10 @@ void ewk_view_download_job_failed(Evas_Object* ewkView, Ewk_Download_Job*, Ewk_W 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*); +#if ENABLE(FULLSCREEN_API) +void ewk_view_full_screen_enter(Evas_Object* ewkView); +void ewk_view_full_screen_exit(Evas_Object* ewkView); +#endif 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); @@ -89,4 +100,6 @@ bool ewk_view_accelerated_compositing_mode_enter(const Evas_Object* ewkView); bool ewk_view_accelerated_compositing_mode_exit(const Evas_Object* ewkView); #endif +void ewk_view_popup_menu_request(Evas_Object* ewkView, WebKit::WebPopupMenuProxyEfl* popupMenu, const WebCore::IntRect&, WebCore::TextDirection, double pageScaleFactor, const Vector<WebKit::WebPopupItem>& items, int32_t selectedIndex); + #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 39bc5a4db..8033e2498 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.cpp +++ b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.cpp @@ -21,7 +21,6 @@ #include "EWK2UnitTestBase.h" #include "EWK2UnitTestEnvironment.h" -#include <EWebKit2.h> #include <Ecore.h> #include <glib-object.h> #include <wtf/UnusedParam.h> @@ -42,7 +41,9 @@ static void onLoadFinished(void* userData, Evas_Object* webView, void* eventInfo EWK2UnitTestBase::EWK2UnitTestBase() : m_ecoreEvas(0) , m_webView(0) + , m_ewkViewClass(EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("Browser_View")) { + ewk_view_smart_class_set(&m_ewkViewClass); } void EWK2UnitTestBase::SetUp() @@ -60,7 +61,8 @@ void EWK2UnitTestBase::SetUp() ecore_evas_show(m_ecoreEvas); Evas* evas = ecore_evas_get(m_ecoreEvas); - m_webView = ewk_view_add(evas); + Evas_Smart* smart = evas_smart_class_new(&m_ewkViewClass.sc); + m_webView = ewk_view_smart_add(evas, smart, ewk_context_default_get()); ewk_view_theme_set(m_webView, environment->defaultTheme()); evas_object_resize(m_webView, width, height); @@ -77,10 +79,15 @@ void EWK2UnitTestBase::TearDown() void EWK2UnitTestBase::loadUrlSync(const char* url) { + ewk_view_uri_set(m_webView, url); + waitUntilLoadFinished(); +} + +void EWK2UnitTestBase::waitUntilLoadFinished() +{ bool loadFinished = false; evas_object_smart_callback_add(m_webView, "load,finished", onLoadFinished, &loadFinished); - ewk_view_uri_set(m_webView, url); while (!loadFinished) ecore_main_loop_iterate(); diff --git a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.h b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.h index 29d55bee4..fa6abd160 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.h +++ b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestBase.h @@ -20,6 +20,7 @@ #ifndef EWK2UnitTestBase_h #define EWK2UnitTestBase_h +#include <EWebKit2.h> #include <Ecore_Evas.h> #include <Evas.h> #include <gtest/gtest.h> @@ -29,6 +30,7 @@ namespace EWK2UnitTest { class EWK2UnitTestBase : public ::testing::Test { public: Evas_Object* webView() { return m_webView; } + Ewk_View_Smart_Class* ewkViewClass() { return &m_ewkViewClass; } protected: EWK2UnitTestBase(); @@ -37,12 +39,14 @@ protected: virtual void TearDown(); void loadUrlSync(const char* url); + void waitUntilLoadFinished(); void waitUntilTitleChangedTo(const char* expectedTitle); void mouseClick(int x, int y); private: Evas_Object* m_webView; Ecore_Evas* m_ecoreEvas; + Ewk_View_Smart_Class m_ewkViewClass; }; } // namespace EWK2UnitTest diff --git a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp index fae77242f..814f8c2cb 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp +++ b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.cpp @@ -20,7 +20,9 @@ #include "config.h" #include "EWK2UnitTestEnvironment.h" +#include <wtf/text/StringBuilder.h> #include <wtf/text/StringConcatenate.h> +#include <wtf/text/WTFString.h> namespace EWK2UnitTest { @@ -46,4 +48,12 @@ CString EWK2UnitTestEnvironment::urlForResource(const char* resource) return makeString("file://"TEST_RESOURCES_DIR"/", resource).utf8(); } +CString EWK2UnitTestEnvironment::pathForResource(const char* resource) +{ + StringBuilder builder; + builder.appendLiteral(TEST_RESOURCES_DIR "/"); + builder.append(resource); + return builder.toString().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 d010b6237..fb3a309f8 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.h +++ b/Source/WebKit2/UIProcess/API/efl/tests/UnitTestUtils/EWK2UnitTestEnvironment.h @@ -33,6 +33,7 @@ public: const char* defaultTestPageUrl() const; const char* defaultTheme() const; CString urlForResource(const char* resource); + CString pathForResource(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/resources/big_button_theme.edj b/Source/WebKit2/UIProcess/API/efl/tests/resources/big_button_theme.edj Binary files differnew file mode 100644 index 000000000..60bb40ff9 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/tests/resources/big_button_theme.edj diff --git a/Source/WebKit2/UIProcess/API/efl/tests/resources/empty_theme.edj b/Source/WebKit2/UIProcess/API/efl/tests/resources/empty_theme.edj Binary files differnew file mode 100644 index 000000000..2d6cd0485 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/tests/resources/empty_theme.edj diff --git a/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_back_forward_list.cpp b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_back_forward_list.cpp index af10981ec..68c15dbb8 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_back_forward_list.cpp +++ b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_back_forward_list.cpp @@ -41,6 +41,7 @@ extern EWK2UnitTestEnvironment* environment; static const char title1[] = "Page1"; static const char title2[] = "Page2"; +static const char title3[] = "Page3"; static void serverCallbackNavigation(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) { @@ -78,6 +79,13 @@ static inline WKEinaSharedString urlFromTitle(EWK2UnitTestServer* httpServer, co return res; } +static inline void freeEinaList(Eina_List* list) +{ + void* data = 0; + EINA_LIST_FREE(list, data) + ewk_back_forward_list_item_unref(static_cast<Ewk_Back_Forward_List_Item*>(data)); +} + TEST_F(EWK2UnitTestBase, ewk_back_forward_list_current_item_get) { const char* url = environment->defaultTestPageUrl(); @@ -181,3 +189,83 @@ TEST_F(EWK2UnitTestBase, ewk_back_forward_list_count) EXPECT_EQ(ewk_back_forward_list_count(backForwardList), 2); } + +TEST_F(EWK2UnitTestBase, ewk_back_forward_list_n_back_items_copy) +{ + OwnPtr<EWK2UnitTestServer> httpServer = adoptPtr(new EWK2UnitTestServer); + httpServer->run(serverCallbackNavigation); + + WKEinaSharedString url1 = urlFromTitle(httpServer.get(), title1); + loadUrlSync(url1); + ASSERT_STREQ(ewk_view_title_get(webView()), title1); + + WKEinaSharedString url2 = urlFromTitle(httpServer.get(), title2); + loadUrlSync(url2); + ASSERT_STREQ(ewk_view_title_get(webView()), title2); + + loadUrlSync(urlFromTitle(httpServer.get(), title3)); + ASSERT_STREQ(ewk_view_title_get(webView()), title3); + + Ewk_Back_Forward_List* backForwardList = ewk_view_back_forward_list_get(webView()); + ASSERT_TRUE(backForwardList); + + Eina_List* backList = ewk_back_forward_list_n_back_items_copy(backForwardList, 1); + ASSERT_TRUE(backList); + ASSERT_EQ(eina_list_count(backList), 1); + checkItem(static_cast<Ewk_Back_Forward_List_Item*>(eina_list_nth(backList, 0)), title2, url2, url2); + freeEinaList(backList); + + // Check '0' limit. + backList = ewk_back_forward_list_n_back_items_copy(backForwardList, 0); + ASSERT_FALSE(backList); + + backList = ewk_back_forward_list_n_back_items_copy(backForwardList, -1); + ASSERT_TRUE(backList); + ASSERT_EQ(eina_list_count(backList), 2); + checkItem(static_cast<Ewk_Back_Forward_List_Item*>(eina_list_nth(backList, 0)), title1, url1, url1); + checkItem(static_cast<Ewk_Back_Forward_List_Item*>(eina_list_nth(backList, 1)), title2, url2, url2); + freeEinaList(backList); +} + +TEST_F(EWK2UnitTestBase, ewk_back_forward_list_n_forward_items_copy) +{ + OwnPtr<EWK2UnitTestServer> httpServer = adoptPtr(new EWK2UnitTestServer); + httpServer->run(serverCallbackNavigation); + + loadUrlSync(urlFromTitle(httpServer.get(), title1)); + ASSERT_STREQ(ewk_view_title_get(webView()), title1); + + WKEinaSharedString url2 = urlFromTitle(httpServer.get(), title2); + loadUrlSync(url2); + ASSERT_STREQ(ewk_view_title_get(webView()), title2); + + WKEinaSharedString url3 = urlFromTitle(httpServer.get(), title3); + loadUrlSync(url3); + ASSERT_STREQ(ewk_view_title_get(webView()), title3); + + // Go back to Page1. + ewk_view_back(webView()); + waitUntilTitleChangedTo(title2); + ewk_view_back(webView()); + waitUntilTitleChangedTo(title1); + + Ewk_Back_Forward_List* backForwardList = ewk_view_back_forward_list_get(webView()); + ASSERT_TRUE(backForwardList); + + Eina_List* forwardList = ewk_back_forward_list_n_forward_items_copy(backForwardList, 1); + ASSERT_TRUE(forwardList); + ASSERT_EQ(eina_list_count(forwardList), 1); + checkItem(static_cast<Ewk_Back_Forward_List_Item*>(eina_list_nth(forwardList, 0)), title2, url2, url2); + freeEinaList(forwardList); + + // Check '0' limit. + forwardList = ewk_back_forward_list_n_forward_items_copy(backForwardList, 0); + ASSERT_FALSE(forwardList); + + forwardList = ewk_back_forward_list_n_forward_items_copy(backForwardList, -1); + ASSERT_TRUE(forwardList); + ASSERT_EQ(eina_list_count(forwardList), 2); + checkItem(static_cast<Ewk_Back_Forward_List_Item*>(eina_list_nth(forwardList, 0)), title2, url2, url2); + checkItem(static_cast<Ewk_Back_Forward_List_Item*>(eina_list_nth(forwardList, 1)), title3, url3, url3); + freeEinaList(forwardList); +} 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 10be26cb5..e0319f7ce 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 @@ -258,7 +258,7 @@ TEST_F(EWK2UnitTestBase, ewk_cookie_manager_cookies_delete) ASSERT_EQ(countHostnamesWithCookies(cookieManager), 0); } -TEST_F(EWK2UnitTestBase, ewk_cookie_manager_permanent_storage) +TEST_F(EWK2UnitTestBase, DISABLED_ewk_cookie_manager_permanent_storage) { OwnPtr<EWK2UnitTestServer> httpServer = adoptPtr(new EWK2UnitTestServer); httpServer->run(serverCallback); diff --git a/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_settings.cpp b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_settings.cpp new file mode 100644 index 000000000..dd0a6e722 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_settings.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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 <EWebKit2.h> +#include <Eina.h> + +using namespace EWK2UnitTest; + +TEST_F(EWK2UnitTestBase, ewk_settings_fullscreen_enabled) +{ + Ewk_Settings* settings = ewk_view_settings_get(webView()); + +#if ENABLE(FULLSCREEN_API) + ASSERT_TRUE(ewk_settings_fullscreen_enabled_get(settings)); + + ASSERT_TRUE(ewk_settings_fullscreen_enabled_set(settings, EINA_TRUE)); + ASSERT_TRUE(ewk_settings_fullscreen_enabled_get(settings)); + + ASSERT_TRUE(ewk_settings_fullscreen_enabled_set(settings, EINA_FALSE)); + ASSERT_FALSE(ewk_settings_fullscreen_enabled_get(settings)); +#else + ASSERT_FALSE(ewk_settings_fullscreen_enabled_get(settings)); + + ASSERT_FALSE(ewk_settings_fullscreen_enabled_set(settings, EINA_TRUE)); + ASSERT_FALSE(ewk_settings_fullscreen_enabled_get(settings)); + + ASSERT_FALSE(ewk_settings_fullscreen_enabled_set(settings, EINA_FALSE)); + ASSERT_FALSE(ewk_settings_fullscreen_enabled_get(settings)); +#endif +} + +TEST_F(EWK2UnitTestBase, ewk_settings_javascript_enabled) +{ + Ewk_Settings* settings = ewk_view_settings_get(webView()); + + ASSERT_TRUE(ewk_settings_javascript_enabled_set(settings, EINA_TRUE)); + ASSERT_TRUE(ewk_settings_javascript_enabled_get(settings)); + + ASSERT_TRUE(ewk_settings_javascript_enabled_set(settings, 2)); + ASSERT_TRUE(ewk_settings_javascript_enabled_get(settings)); + + ASSERT_TRUE(ewk_settings_javascript_enabled_set(settings, EINA_FALSE)); + ASSERT_FALSE(ewk_settings_javascript_enabled_get(settings)); +} + +TEST_F(EWK2UnitTestBase, ewk_settings_loads_images_automatically) +{ + Ewk_Settings* settings = ewk_view_settings_get(webView()); + + ASSERT_TRUE(ewk_settings_loads_images_automatically_set(settings, EINA_TRUE)); + ASSERT_TRUE(ewk_settings_loads_images_automatically_get(settings)); + + ASSERT_TRUE(ewk_settings_loads_images_automatically_set(settings, 2)); + ASSERT_TRUE(ewk_settings_loads_images_automatically_get(settings)); + + ASSERT_TRUE(ewk_settings_loads_images_automatically_set(settings, EINA_FALSE)); + ASSERT_FALSE(ewk_settings_loads_images_automatically_get(settings)); +} 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 5edb04379..6e928edd9 100644 --- a/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_view.cpp +++ b/Source/WebKit2/UIProcess/API/efl/tests/test_ewk2_view.cpp @@ -24,6 +24,7 @@ #include "UnitTestUtils/EWK2UnitTestServer.h" #include <EWebKit2.h> #include <Ecore.h> +#include <Eina.h> #include <gtest/gtest.h> #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> @@ -33,6 +34,7 @@ using namespace EWK2UnitTest; extern EWK2UnitTestEnvironment* environment; +bool fullScreenCallbackCalled; static void onLoadFinishedForRedirection(void* userData, Evas_Object*, void*) { @@ -188,3 +190,173 @@ TEST_F(EWK2UnitTestBase, ewk_view_form_submission_request) ASSERT_TRUE(handled); evas_object_smart_callback_del(webView(), "form,submission,request", onFormAboutToBeSubmitted); } + +static inline void checkBasicPopupMenuItem(Ewk_Popup_Menu_Item* item, const char* title, bool enabled) +{ + EXPECT_EQ(ewk_popup_menu_item_type_get(item), EWK_POPUP_MENU_ITEM); + EXPECT_STREQ(ewk_popup_menu_item_text_get(item), title); + EXPECT_EQ(ewk_popup_menu_item_enabled_get(item), enabled); +} + +static Eina_Bool selectItemAfterDelayed(void* data) +{ + EXPECT_TRUE(ewk_view_popup_menu_select(static_cast<Evas_Object*>(data), 0)); + return ECORE_CALLBACK_CANCEL; +} + +static Eina_Bool showPopupMenu(Ewk_View_Smart_Data* smartData, Eina_Rectangle, Ewk_Text_Direction, double, Eina_List* list, int selectedIndex) +{ + EXPECT_EQ(selectedIndex, 2); + + Ewk_Popup_Menu_Item* item = static_cast<Ewk_Popup_Menu_Item*>(eina_list_nth(list, 0)); + checkBasicPopupMenuItem(item, "first", true); + EXPECT_EQ(ewk_popup_menu_item_text_direction_get(item), EWK_TEXT_DIRECTION_LEFT_TO_RIGHT); + EXPECT_STREQ(ewk_popup_menu_item_tooltip_get(item), ""); + EXPECT_STREQ(ewk_popup_menu_item_accessibility_text_get(item), ""); + EXPECT_FALSE(ewk_popup_menu_item_is_label_get(item)); + EXPECT_FALSE(ewk_popup_menu_item_selected_get(item)); + + item = static_cast<Ewk_Popup_Menu_Item*>(eina_list_nth(list, 1)); + checkBasicPopupMenuItem(item, "second", false); + EXPECT_EQ(ewk_popup_menu_item_enabled_get(item), false); + + item = static_cast<Ewk_Popup_Menu_Item*>(eina_list_nth(list, 2)); + checkBasicPopupMenuItem(item, "third", true); + EXPECT_EQ(ewk_popup_menu_item_text_direction_get(item), EWK_TEXT_DIRECTION_RIGHT_TO_LEFT); + EXPECT_STREQ(ewk_popup_menu_item_tooltip_get(item), "tooltip"); + EXPECT_STREQ(ewk_popup_menu_item_accessibility_text_get(item), "aria"); + EXPECT_TRUE(ewk_popup_menu_item_selected_get(item)); + + item = static_cast<Ewk_Popup_Menu_Item*>(eina_list_nth(list, 3)); + checkBasicPopupMenuItem(item, "label", false); + EXPECT_TRUE(ewk_popup_menu_item_is_label_get(item)); + + item = static_cast<Ewk_Popup_Menu_Item*>(eina_list_nth(list, 4)); + checkBasicPopupMenuItem(item, " forth", true); + + item = static_cast<Ewk_Popup_Menu_Item*>(eina_list_nth(list, 5)); + EXPECT_EQ(ewk_popup_menu_item_type_get(item), EWK_POPUP_MENU_UNKNOWN); + EXPECT_STREQ(ewk_popup_menu_item_text_get(item), 0); + + ecore_timer_add(0, selectItemAfterDelayed, smartData->self); + return true; +} + +TEST_F(EWK2UnitTestBase, ewk_view_popup_menu_select) +{ + const char* selectHTML = + "<!doctype html><body><select onchange=\"document.title=this.value;\">" + "<option>first</option><option disabled>second</option><option selected dir=\"rtl\" title=\"tooltip\" aria-label=\"aria\">third</option>" + "<optgroup label=\"label\"><option>forth</option></optgroup>" + "</select></body>"; + + ewkViewClass()->popup_menu_show = showPopupMenu; + + ewk_view_html_string_load(webView(), selectHTML, "file:///", 0); + waitUntilLoadFinished(); + mouseClick(30, 20); + waitUntilTitleChangedTo("first"); + + EXPECT_TRUE(ewk_view_popup_menu_close(webView())); + EXPECT_FALSE(ewk_view_popup_menu_select(webView(), 0)); +} + +TEST_F(EWK2UnitTestBase, ewk_view_settings_get) +{ + Ewk_Settings* settings = ewk_view_settings_get(webView()); + ASSERT_TRUE(settings); + ASSERT_EQ(settings, ewk_view_settings_get(webView())); +} + +TEST_F(EWK2UnitTestBase, ewk_view_theme_set) +{ + const char* buttonHTML = "<html><body><input type='button' id='btn'>" + "<script>document.title=document.getElementById('btn').clientWidth;</script>" + "</body></html>"; + + ewk_view_html_string_load(webView(), buttonHTML, "file:///", 0); + waitUntilTitleChangedTo("30"); // button of default theme has 30px as padding (15 to -16) + + ewk_view_theme_set(webView(), environment->pathForResource("it_does_not_exist.edj").data()); + ewk_view_html_string_load(webView(), buttonHTML, "file:///", 0); + waitUntilTitleChangedTo("30"); // the result should be same as default theme + + ewk_view_theme_set(webView(), environment->pathForResource("empty_theme.edj").data()); + ewk_view_html_string_load(webView(), buttonHTML, "file:///", 0); + waitUntilTitleChangedTo("30"); // the result should be same as default theme + + ewk_view_theme_set(webView(), environment->pathForResource("big_button_theme.edj").data()); + ewk_view_html_string_load(webView(), buttonHTML, "file:///", 0); + waitUntilTitleChangedTo("299"); // button of big button theme has 299px as padding (150 to -150) +} + +TEST_F(EWK2UnitTestBase, ewk_view_mouse_events_enabled) +{ + ASSERT_TRUE(ewk_view_mouse_events_enabled_set(webView(), EINA_TRUE)); + ASSERT_TRUE(ewk_view_mouse_events_enabled_get(webView())); + + ASSERT_TRUE(ewk_view_mouse_events_enabled_set(webView(), 2)); + ASSERT_TRUE(ewk_view_mouse_events_enabled_get(webView())); + + ASSERT_TRUE(ewk_view_mouse_events_enabled_set(webView(), EINA_FALSE)); + ASSERT_FALSE(ewk_view_mouse_events_enabled_get(webView())); +} + +static Eina_Bool fullScreenCallback(Ewk_View_Smart_Data* smartData) +{ + fullScreenCallbackCalled = true; + return false; +} + +static void checkFullScreenProperty(Evas_Object* webView, bool expectedState) +{ + if (environment->useX11Window()) { + Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(webView)); + Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(smartData->base.evas); + bool windowState = false; + while (((windowState = ecore_evas_fullscreen_get(ecoreEvas)) != expectedState)) + ecore_main_loop_iterate(); + ASSERT_TRUE(expectedState == windowState); + } +} + +TEST_F(EWK2UnitTestBase, ewk_view_full_screen_enter) +{ + const char fullscreenHTML[] = + "<!doctype html><head><script>function makeFullScreen(){" + "var div = document.getElementById(\"fullscreen\");" + "div.webkitRequestFullScreen();" + "document.title = \"fullscreen entered\";" + "}</script></head>" + "<body><div id=\"fullscreen\" style=\"width:100px; height:100px\" onclick=\"makeFullScreen()\"></div></body>"; + + ewkViewClass()->fullscreen_enter = fullScreenCallback; + + ewk_view_html_string_load(webView(), fullscreenHTML, "file:///", 0); + waitUntilLoadFinished(); + mouseClick(50, 50); + waitUntilTitleChangedTo("fullscreen entered"); + ASSERT_TRUE(fullScreenCallbackCalled); + checkFullScreenProperty(webView(), true); +} + +TEST_F(EWK2UnitTestBase, ewk_view_full_screen_exit) +{ + const char fullscreenHTML[] = + "<!doctype html><head><script>function makeFullScreenAndExit(){" + "var div = document.getElementById(\"fullscreen\");" + "div.webkitRequestFullScreen();" + "document.webkitCancelFullScreen();" + "document.title = \"fullscreen exited\";" + "}</script></head>" + "<body><div id=\"fullscreen\" style=\"width:100px; height:100px\" onclick=\"makeFullScreenAndExit()\"></div></body>"; + + ewkViewClass()->fullscreen_exit = fullScreenCallback; + + ewk_view_html_string_load(webView(), fullscreenHTML, "file:///", 0); + waitUntilLoadFinished(); + mouseClick(50, 50); + waitUntilTitleChangedTo("fullscreen exited"); + ASSERT_TRUE(fullScreenCallbackCalled); + checkFullScreenProperty(webView(), false); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp index 5a6adae0a..a1f5d962d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp @@ -233,7 +233,7 @@ PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPagePr } #if ENABLE(INPUT_TYPE_COLOR) -PassRefPtr<WebColorChooserProxy> PageClientImpl::createColorChooserProxy(WebPageProxy*, const WebCore::Color&) +PassRefPtr<WebColorChooserProxy> PageClientImpl::createColorChooserProxy(WebPageProxy*, const WebCore::Color&, const WebCore::IntRect&) { notImplemented(); return 0; diff --git a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h index 72fc34539..f4afd06d9 100644 --- a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h +++ b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h @@ -51,7 +51,7 @@ public: GtkWidget* viewWidget() { return m_viewWidget; } private: - PageClientImpl(GtkWidget*); + explicit PageClientImpl(GtkWidget*); virtual PassOwnPtr<DrawingAreaProxy> createDrawingAreaProxy(); virtual void setViewNeedsDisplay(const WebCore::IntRect&); @@ -82,7 +82,7 @@ private: virtual PassRefPtr<WebPopupMenuProxy> createPopupMenuProxy(WebPageProxy*); virtual PassRefPtr<WebContextMenuProxy> createContextMenuProxy(WebPageProxy*); #if ENABLE(INPUT_TYPE_COLOR) - virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& intialColor); + virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& intialColor, const WebCore::IntRect&); #endif virtual void setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut, bool animate); virtual void didChangeScrollbarsForMainFrame() const; diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.cpp index e0d7a60ea..aa2623783 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.cpp @@ -98,7 +98,9 @@ static gboolean webkitDownloadDecideDestination(WebKitDownload* download, const { if (!download->priv->destinationURI.isNull()) return FALSE; - GOwnPtr<char> destination(g_build_filename(g_get_user_special_dir(G_USER_DIRECTORY_DOWNLOAD), suggestedFilename, NULL)); + + GOwnPtr<char> filename(g_strdelimit(g_strdup(suggestedFilename), G_DIR_SEPARATOR_S, '_')); + GOwnPtr<char> destination(g_build_filename(g_get_user_special_dir(G_USER_DIRECTORY_DOWNLOAD), filename.get(), NULL)); GOwnPtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0)); download->priv->destinationURI = destinationURI.get(); g_object_notify(G_OBJECT(download), "destination"); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp index 1cd8aaf7f..b38161156 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp @@ -38,7 +38,7 @@ using namespace WebKit; static void didInitiateLoadForResource(WKPageRef, WKFrameRef wkFrame, uint64_t resourceIdentifier, WKURLRequestRef wkRequest, bool pageIsProvisionallyLoading, const void* clientInfo) { GRefPtr<WebKitURIRequest> request = adoptGRef(webkitURIRequestCreateForResourceRequest(toImpl(wkRequest)->resourceRequest())); - webkitWebViewResourceLoadStarted(WEBKIT_WEB_VIEW(clientInfo), wkFrame, resourceIdentifier, request.get(), pageIsProvisionallyLoading); + webkitWebViewResourceLoadStarted(WEBKIT_WEB_VIEW(clientInfo), wkFrame, resourceIdentifier, request.get()); } static void didSendRequestForResource(WKPageRef, WKFrameRef, uint64_t resourceIdentifier, WKURLRequestRef wkRequest, WKURLResponseRef wkRedirectResponse, const void* clientInfo) diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp index ee86d448a..6fefb652b 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp @@ -1311,11 +1311,12 @@ static void waitForMainResourceResponseIfWaitingForResource(WebKitWebView* webVi g_signal_connect(priv->mainResource.get(), "notify::response", G_CALLBACK(mainResourceResponseChangedCallback), webView); } -void webkitWebViewResourceLoadStarted(WebKitWebView* webView, WKFrameRef wkFrame, uint64_t resourceIdentifier, WebKitURIRequest* request, bool isMainResource) +void webkitWebViewResourceLoadStarted(WebKitWebView* webView, WKFrameRef wkFrame, uint64_t resourceIdentifier, WebKitURIRequest* request) { WebKitWebViewPrivate* priv = webView->priv; + bool isMainResource = WKFrameIsMainFrame(wkFrame) && !priv->mainResource; WebKitWebResource* resource = webkitWebResourceCreate(wkFrame, request, isMainResource); - if (WKFrameIsMainFrame(wkFrame) && (isMainResource || !priv->mainResource)) { + if (isMainResource) { priv->mainResource = resource; waitForMainResourceResponseIfWaitingForResource(webView); } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp index 4925b5a7c..f5bd2ddcc 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp @@ -147,6 +147,9 @@ static void webkitWebViewBaseRealize(GtkWidget* widget) | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK +#if GTK_CHECK_VERSION(3, 3, 18) + | GDK_SMOOTH_SCROLL_MASK +#endif | GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h index f2986d1f9..5ad2853bb 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h @@ -47,7 +47,7 @@ void webkitWebViewMakePermissionRequest(WebKitWebView*, WebKitPermissionRequest* void webkitWebViewMakePolicyDecision(WebKitWebView*, WebKitPolicyDecisionType, WebKitPolicyDecision*); void webkitWebViewMouseTargetChanged(WebKitWebView*, WKHitTestResultRef, unsigned modifiers); void webkitWebViewPrintFrame(WebKitWebView*, WKFrameRef); -void webkitWebViewResourceLoadStarted(WebKitWebView*, WKFrameRef, uint64_t resourceIdentifier, WebKitURIRequest*, bool isMainResource); +void webkitWebViewResourceLoadStarted(WebKitWebView*, WKFrameRef, uint64_t resourceIdentifier, WebKitURIRequest*); void webkitWebViewRunFileChooserRequest(WebKitWebView*, WebKitFileChooserRequest*); WebKitWebResource* webkitWebViewGetLoadingWebResource(WebKitWebView*, uint64_t resourceIdentifier); void webkitWebViewRemoveLoadingWebResource(WebKitWebView*, uint64_t resourceIdentifier); diff --git a/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm b/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm index 6a02f562d..4df0ef1c4 100644 --- a/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm +++ b/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm @@ -36,7 +36,8 @@ #import "WebPreferences.h" #import <PDFKit/PDFKit.h> #import <WebCore/LocalizedStrings.h> -#import <objc/runtime.h> +#import <objc/objc-runtime.h> +#import <wtf/ObjcRuntimeExtras.h> #import <wtf/text/CString.h> #import <wtf/text/WTFString.h> @@ -537,7 +538,7 @@ static void PDFViewScrollView_scrollWheel(NSScrollView* self, SEL _cmd, NSEvent } } - oldPDFViewScrollView_scrollWheel(self, _cmd, wheelEvent); + wtfCallIMP<void>(oldPDFViewScrollView_scrollWheel, self, _cmd, wheelEvent); } #endif diff --git a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h index 98da7eceb..18579eee9 100644 --- a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h +++ b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h @@ -48,7 +48,7 @@ public: void viewWillMoveToAnotherWindow(); private: - PageClientImpl(WKView*); + explicit PageClientImpl(WKView*); virtual PassOwnPtr<DrawingAreaProxy> createDrawingAreaProxy(); virtual void setViewNeedsDisplay(const WebCore::IntRect&); @@ -97,7 +97,7 @@ private: virtual PassRefPtr<WebContextMenuProxy> createContextMenuProxy(WebPageProxy*); #if ENABLE(INPUT_TYPE_COLOR) - virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& initialColor); + virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& initialColor, const WebCore::IntRect&); #endif void setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut, bool animate); diff --git a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm index b31946b3c..7b54b4bd7 100644 --- a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm +++ b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm @@ -366,7 +366,7 @@ PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPagePr } #if ENABLE(INPUT_TYPE_COLOR) -PassRefPtr<WebColorChooserProxy> PageClientImpl::createColorChooserProxy(WebPageProxy*, const WebCore::Color&) +PassRefPtr<WebColorChooserProxy> PageClientImpl::createColorChooserProxy(WebPageProxy*, const WebCore::Color&, const WebCore::IntRect&) { notImplemented(); return 0; diff --git a/Source/WebKit2/UIProcess/API/mac/WKView.mm b/Source/WebKit2/UIProcess/API/mac/WKView.mm index eb6b819c5..98e32662a 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKView.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKView.mm @@ -1937,6 +1937,7 @@ static NSString * const backingPropertyOldScaleFactorKey = @"NSBackingPropertyOl [self _accessibilityRegisterUIProcessTokens]; } else { + [self _updateWindowVisibility]; _data->_page->viewStateDidChange(WebPageProxy::ViewIsVisible); _data->_page->viewStateDidChange(WebPageProxy::ViewWindowIsActive | WebPageProxy::ViewIsInWindow); diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p_p.h index ad1c6ad3f..c7ac86c3d 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p_p.h @@ -26,7 +26,6 @@ namespace WebKit { class WebPageProxy; -class QtViewportHandler; class QtWebPageEventHandler; } diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp index 921586d1b..490b9ba7c 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp @@ -23,9 +23,9 @@ #include "DownloadProxy.h" #include "DrawingAreaProxyImpl.h" +#include "PageViewportControllerClientQt.h" #include "QtDialogRunner.h" #include "QtDownloadManager.h" -#include "QtViewportHandler.h" #include "QtWebContext.h" #include "QtWebError.h" #include "QtWebIconDatabaseClient.h" @@ -272,6 +272,7 @@ QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport) , m_navigatorQtObjectEnabled(false) , m_renderToOffscreenBuffer(false) , m_allowAnyHTTPSCertificateForLocalHost(false) + , m_customDevicePixelRatio(0) , m_loadProgress(0) { viewport->setClip(true); @@ -325,8 +326,9 @@ void QQuickWebViewPrivate::initialize(WKContextRef contextRef, WKPageGroupRef pa void QQuickWebViewPrivate::onComponentComplete() { Q_Q(QQuickWebView); - m_viewportHandler.reset(new QtViewportHandler(webPageProxy.get(), q, pageView.data())); - pageView->eventHandler()->setViewportHandler(m_viewportHandler.data()); + m_pageViewportControllerClient.reset(new PageViewportControllerClientQt(q, pageView.data())); + m_pageViewportController.reset(new PageViewportController(webPageProxy.get(), m_pageViewportControllerClient.data())); + pageView->eventHandler()->setViewportController(m_pageViewportControllerClient.data()); } void QQuickWebViewPrivate::setTransparentBackground(bool enable) @@ -473,7 +475,10 @@ void QQuickWebViewPrivate::didRelaunchProcess() { qWarning("WARNING: The web process has been successfully restarted."); + // Reset to default so that the later update can reach the web process. + webPageProxy->setCustomDeviceScaleFactor(0); webPageProxy->drawingArea()->setSize(viewSize(), IntSize()); + updateViewportSize(); updateUserScripts(); } @@ -789,6 +794,20 @@ void QQuickWebViewPrivate::didReceiveMessageFromNavigatorQtObject(const String& emit q_ptr->experimental()->messageReceived(variantMap); } +void QQuickWebViewPrivate::didChangeContentsSize(const QSize& newSize) +{ + if (newSize.isEmpty() || !m_customDevicePixelRatio || webPageProxy->deviceScaleFactor() == m_customDevicePixelRatio) + return; + + // DrawingAreaProxy returns early if the page size is empty + // and the device pixel ratio property is propagated from QML + // before the QML page item has a valid size yet, thus the + // information would not reach the web process. + // Set the custom device pixel ratio requested from QML as soon + // as the content item has a valid size. + webPageProxy->setCustomDeviceScaleFactor(m_customDevicePixelRatio); +} + QQuickWebViewLegacyPrivate::QQuickWebViewLegacyPrivate(QQuickWebView* viewport) : QQuickWebViewPrivate(viewport) { @@ -836,11 +855,6 @@ QQuickWebViewFlickablePrivate::QQuickWebViewFlickablePrivate(QQuickWebView* view viewport->setAcceptHoverEvents(false); } -QQuickWebViewFlickablePrivate::~QQuickWebViewFlickablePrivate() -{ - m_viewportHandler->disconnect(); -} - void QQuickWebViewFlickablePrivate::initialize(WKContextRef contextRef, WKPageGroupRef pageGroupRef) { QQuickWebViewPrivate::initialize(contextRef, pageGroupRef); @@ -856,28 +870,29 @@ void QQuickWebViewFlickablePrivate::onComponentComplete() void QQuickWebViewFlickablePrivate::didChangeViewportProperties(const WebCore::ViewportAttributes& newAttributes) { - if (m_viewportHandler) - m_viewportHandler->viewportAttributesChanged(newAttributes); + if (m_pageViewportController) + m_pageViewportController->didChangeViewportAttributes(newAttributes); } void QQuickWebViewFlickablePrivate::updateViewportSize() { - // FIXME: Examine why there is not an viewportHandler here in the beginning. - if (m_viewportHandler) - m_viewportHandler->viewportItemSizeChanged(); + Q_Q(QQuickWebView); + + if (m_pageViewportController) + m_pageViewportController->setViewportSize(QSizeF(q->width(), q->height())); } void QQuickWebViewFlickablePrivate::pageDidRequestScroll(const QPoint& pos) { - m_viewportHandler->pageContentPositionRequested(pos); + if (m_pageViewportController) + m_pageViewportController->pageDidRequestScroll(pos); } void QQuickWebViewFlickablePrivate::didChangeContentsSize(const QSize& newSize) { - Q_Q(QQuickWebView); - pageView->setContentsSize(newSize); // emits contentsSizeChanged() - m_viewportHandler->pageContentsSizeChanged(newSize, q->boundingRect().size().toSize()); + QQuickWebViewPrivate::didChangeContentsSize(newSize); + m_pageViewportController->didChangeContentsSize(newSize); } void QQuickWebViewFlickablePrivate::handleMouseEvent(QMouseEvent* event) @@ -889,22 +904,6 @@ void QQuickWebViewFlickablePrivate::handleMouseEvent(QMouseEvent* event) pageView->eventHandler()->handleInputEvent(event); } -/*! - \qmlsignal WebView::onNavigationRequested(WebNavigationRequest request) - - This signal is emitted for every navigation request. The request object contains url, - button and modifiers properties describing the navigation action, e.g. "a middle click - with shift key pressed to 'http://qt-project.org'". - - The navigation will be accepted by default. To change that, one can set the action - property to WebView.IgnoreRequest to reject the request or WebView.DownloadRequest to - trigger a download instead of navigating to the url. - - The request object cannot be used after the signal handler function ends. - - \sa WebNavigationRequest -*/ - QQuickWebViewExperimental::QQuickWebViewExperimental(QQuickWebView *webView) : QObject(webView) , q_ptr(webView) @@ -1233,19 +1232,23 @@ void QQuickWebViewExperimental::setUserAgent(const QString& userAgent) down but still provide a better looking image. */ -double QQuickWebViewExperimental::devicePixelRatio() const +qreal QQuickWebViewExperimental::devicePixelRatio() const { Q_D(const QQuickWebView); + + if (d->m_customDevicePixelRatio) + return d->m_customDevicePixelRatio; + return d->webPageProxy->deviceScaleFactor(); } -void QQuickWebViewExperimental::setDevicePixelRatio(double devicePixelRatio) +void QQuickWebViewExperimental::setDevicePixelRatio(qreal devicePixelRatio) { Q_D(QQuickWebView); - if (devicePixelRatio == this->devicePixelRatio()) + if (0 >= devicePixelRatio || devicePixelRatio == this->devicePixelRatio()) return; - d->webPageProxy->setCustomDeviceScaleFactor(devicePixelRatio); + d->m_customDevicePixelRatio = devicePixelRatio; emit devicePixelRatioChanged(); } @@ -1427,13 +1430,55 @@ QQuickWebPage* QQuickWebViewExperimental::page() } /*! - \qmlclass WebView QWebView - \inqmlmodule QtWebKit 3.0 + \page index.html + + \title QtWebKit: QML WebView version 3.0 + + The WebView API allows QML applications to render regions of dynamic + web content. A \e{WebView} component may share the screen with other + QML components or encompass the full screen as specified within the + QML application. + + QML WebView version 3.0 is incompatible with previous QML WebView API + versions. It allows an application to load pages into the WebView, + either by URL or with an HTML string, and navigate within session + history. By default, links to different pages load within the same + WebView, but applications may intercept requests to delegate links to + other functions. + + This sample QML application loads a web page, responds to session + history context, and intercepts requests for external links: + + \code + import QtQuick 2.0 + import QtWebKit 3.0 + + Page { + WebView { + id: webview + url: "http://qt-project.org" + width: parent.width + height: parent.height + onNavigationRequested: { + // detect URL scheme prefix, most likely an external link + var schemaRE = /^\w+:/; + if (schemaRE.test(request.url)) { + request.action = WebView.AcceptRequest; + } else { + request.action = WebView.IgnoreRequest; + // delegate request.url here + } + } + } + } + \endcode */ + /*! - \qmlmethod WebView(Item parent) - \brief Constructs a WebView with a parent. + \qmltype WebView + \inqmlmodule QtWebKit 3.0 + \brief A WebView renders web content within a QML application */ QQuickWebView::QQuickWebView(QQuickItem* parent) @@ -1464,24 +1509,49 @@ QQuickWebPage* QQuickWebView::page() return d->pageView.data(); } +/*! + \qmlmethod void WebView::goBack() + + Go backward within the browser's session history, if possible. + (Equivalent to the \c{window.history.back()} DOM method.) + + \sa WebView::canGoBack +*/ void QQuickWebView::goBack() { Q_D(QQuickWebView); d->webPageProxy->goBack(); } +/*! + \qmlmethod void WebView::goForward() + + Go forward within the browser's session history, if possible. + (Equivalent to the \c{window.history.forward()} DOM method.) +*/ void QQuickWebView::goForward() { Q_D(QQuickWebView); d->webPageProxy->goForward(); } +/*! + \qmlmethod void WebView::stop() + + Stop loading the current page. +*/ void QQuickWebView::stop() { Q_D(QQuickWebView); d->webPageProxy->stopLoading(); } +/*! + \qmlmethod void WebView::reload() + + Reload the current page. (Equivalent to the + \c{window.location.reload()} DOM method.) +*/ void QQuickWebView::reload() { Q_D(QQuickWebView); @@ -1502,6 +1572,15 @@ void QQuickWebView::reload() d->webPageProxy->reload(reloadFromOrigin); } +/*! + \qmlproperty url WebView::url + + The location of the currently displaying HTML page. This writable + property offers the main interface to load a page into a web view. + It functions the same as the \c{window.location} DOM property. + + \sa WebView::loadHtml() +*/ QUrl QQuickWebView::url() const { Q_D(const QQuickWebView); @@ -1535,6 +1614,24 @@ void QQuickWebView::emitUrlChangeIfNeeded() } } +/*! + \qmlproperty url WebView::icon + + The location of the currently displaying Web site icon, also known as favicon + or shortcut icon. This read-only URL corresponds to the image used within a + mobile browser application to represent a bookmarked page on the device's home + screen. + + This example uses the \c{icon} property to build an \c{Image} element: + + \code + Image { + id: appIcon + source: webView.icon != "" ? webView.icon : "fallbackFavIcon.png"; + ... + } + \endcode +*/ QUrl QQuickWebView::icon() const { Q_D(const QQuickWebView); @@ -1543,23 +1640,34 @@ QUrl QQuickWebView::icon() const /*! \qmlproperty int WebView::loadProgress - \brief The progress of loading the current web page. - The range is from 0 to 100. + The amount of the page that has been loaded, expressed as an integer + percentage in the range from \c{0} to \c{100}. */ - int QQuickWebView::loadProgress() const { Q_D(const QQuickWebView); return d->loadProgress(); } +/*! + \qmlproperty bool WebView::canGoBack + + Returns \c{true} if there are prior session history entries, \c{false} + otherwise. +*/ bool QQuickWebView::canGoBack() const { Q_D(const QQuickWebView); return d->webPageProxy->canGoBack(); } +/*! + \qmlproperty bool WebView::canGoForward + + Returns \c{true} if there are subsequent session history entries, + \c{false} otherwise. +*/ bool QQuickWebView::canGoForward() const { Q_D(const QQuickWebView); @@ -1568,9 +1676,9 @@ bool QQuickWebView::canGoForward() const /*! \qmlproperty bool WebView::loading - \brief True if the web view is currently loading a web page, false otherwise. -*/ + Returns \c{true} if the HTML page is currently loading, \c{false} otherwise. +*/ bool QQuickWebView::loading() const { Q_D(const QQuickWebView); @@ -1619,9 +1727,10 @@ QRectF QQuickWebView::mapRectFromWebContent(const QRectF& rectInCSSCoordinates) /*! \qmlproperty string WebView::title - \brief The title of the loaded page. -*/ + The title of the currently displaying HTML page, a read-only value + that reflects the contents of the \c{<title>} tag. +*/ QString QQuickWebView::title() const { Q_D(const QQuickWebView); @@ -1657,7 +1766,7 @@ QVariant QQuickWebView::inputMethodQuery(Qt::InputMethodQuery property) const } /*! - \preliminary + internal The experimental module consisting on experimental API which will break from version to version. @@ -1901,8 +2010,14 @@ void QQuickWebView::handleFlickableMouseRelease(const QPointF& position, qint64 \qmlmethod void WebView::loadHtml(string html, url baseUrl, url unreachableUrl) \brief Loads the specified \a html as the content of the web view. + (This method offers a lower-level alternative to the \c{url} property, + which references HTML pages via URL.) + External objects such as stylesheets or images referenced in the HTML - document are located relative to \a baseUrl. + document are located relative to \a baseUrl. For example if provided \a html + was originally retrieved from \c http://www.example.com/documents/overview.html + and that was the base url, then an image referenced with the relative url \c diagram.png + would be looked for at \c{http://www.example.com/documents/diagram.png}. If an \a unreachableUrl is passed it is used as the url for the loaded content. This is typically used to display error pages for a failed @@ -1955,5 +2070,201 @@ void QQuickWebView::setAllowAnyHTTPSCertificateForLocalHost(bool allow) d->m_allowAnyHTTPSCertificateForLocalHost = allow; } +/*! + \qmlsignal WebView::onLoadingChanged(loadRequest) + + Occurs when any page load begins, ends, or fails. Various read-only + parameters are available on the \a loadRequest: + + \list + + \li \c{url}: the location of the resource that is loading. + + \li \c{status}: Reflects one of three load states: + \c{LoadStartedStatus}, \c{LoadSucceededStatus}, or + \c{LoadFailedStatus}. See \c{WebView::LoadStatus}. + + \li \c{errorString}: description of load error. + + \li \c{errorCode}: HTTP error code. + + \li \c{errorDomain}: high-level error types, one of + \c{NetworkErrorDomain}, \c{HttpErrorDomain}, \c{InternalErrorDomain}, + \c{DownloadErrorDomain}, or \c{NoErrorDomain}. See + \l{WebView::ErrorDomain}. + + \endlist + + \sa WebView::loading +*/ + +/*! + \qmlsignal WebView::onLinkHovered(hoveredUrl, hoveredTitle) + + Within a mouse-driven interface, this signal is emitted when a mouse + pointer passes over a link, corresponding to the \c{mouseover} DOM + event. (May also occur in touch interfaces for \c{mouseover} events + that are not cancelled with \c{preventDefault()}.) The \a{hoveredUrl} + provides the link's location, and the \a{hoveredTitle} is any avalable + link text. +*/ + +/*! + \qmlsignal WebView::onNavigationRequested(request) + + Occurs for various kinds of navigation. If the application listens + for this signal, it must set the \c{request.action} to either of the + following \l{WebView::NavigationRequestAction} enum values: + + \list + + \li \c{AcceptRequest}: Allow navigation to external pages within the + web view. This represents the default behavior when no listener is + active. + + \li \c{IgnoreRequest}: Suppress navigation to new pages within the web + view. (The listener may then delegate navigation externally to + the browser application.) + + \endlist + + The \a{request} also provides the following read-only values: + + \list + + \li \c{url}: The location of the requested page. + + \li \c{navigationType}: contextual information, one of + \c{LinkClickedNavigation}, \c{BackForwardNavigation}, + \c{ReloadNavigation}, \c{FormSubmittedNavigation}, + \c{FormResubmittedNavigation}, or \c{OtherNavigation} enum values. + See \l{WebView::NavigationType}. + + \li \c{keyboardModifiers}: potential states for \l{Qt::KeyboardModifier}. + + \li \c{mouseButton}: potential states for \l{Qt::MouseButton}. + + \endlist +*/ + +/*! + \qmlproperty enumeration WebView::ErrorDomain + + Details various high-level error types. + + \table + + \header + \li Constant + \li Description + + \row + \li InternalErrorDomain + \li Content fails to be interpreted by QtWebKit. + + \row + \li NetworkErrorDomain + \li Error results from faulty network connection. + + \row + \li HttpErrorDomain + \li Error is produced by server. + + \row + \li DownloadErrorDomain + \li Error in saving file. + + \row + \li NoErrorDomain + \li Unspecified fallback error. + + \endtable +*/ + +/*! + \qmlproperty enumeration WebView::NavigationType + + Distinguishes context for various navigation actions. + + \table + + \header + \li Constant + \li Description + + \row + \li LinkClickedNavigation + \li Navigation via link. + + \row + \li FormSubmittedNavigation + \li Form data is posted. + + \row + \li BackForwardNavigation + \li Navigation back and forth within session history. + + \row + \li ReloadNavigation + \li The current page is reloaded. + + \row + \li FormResubmittedNavigation + \li Form data is re-posted. + + \row + \li OtherNavigation + \li Unspecified fallback method of navigation. + + \endtable +*/ + +/*! + \qmlproperty enumeration WebView::LoadStatus + + Reflects a page's load status. + + \table + + \header + \li Constant + \li Description + + \row + \li LoadStartedStatus + \li Page is currently loading. + + \row + \li LoadSucceededStatus + \li Page has successfully loaded, and is not currently loading. + + \row + \li LoadFailedStatus + \li Page has failed to load, and is not currently loading. + + \endtable +*/ + +/*! + \qmlproperty enumeration WebView::NavigationRequestAction + + Specifies a policy when navigating a link to an external page. + + \table + + \header + \li Constant + \li Description + + \row + \li AcceptRequest + \li Allow navigation to external pages within the web view. + + \row + \li IgnoreRequest + \li Suppress navigation to new pages within the web view. + + \endtable +*/ #include "moc_qquickwebview_p.cpp" diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h index 8d0f4ffb9..68e5fca30 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h @@ -48,8 +48,8 @@ class PlatformWebView; } namespace WebKit { -class QtRefCountedNetworkRequestData; -class QtViewportHandler; +struct QtRefCountedNetworkRequestData; +class PageViewportControllerClientQt; class QtWebPageLoadClient; class QtWebPagePolicyClient; class QtWebPageUIClient; @@ -217,7 +217,7 @@ private: QQuickWebViewExperimental* m_experimental; friend class QWebKitTest; - friend class WebKit::QtViewportHandler; + friend class WebKit::PageViewportControllerClientQt; friend class WebKit::QtWebPageLoadClient; friend class WebKit::QtWebPagePolicyClient; friend class WebKit::QtWebPageUIClient; @@ -255,7 +255,7 @@ class QWEBKIT_EXPORT QQuickWebViewExperimental : public QObject { Q_PROPERTY(int preferredMinimumContentsWidth WRITE setPreferredMinimumContentsWidth READ preferredMinimumContentsWidth NOTIFY preferredMinimumContentsWidthChanged) Q_PROPERTY(int deviceWidth WRITE setDeviceWidth READ deviceWidth NOTIFY deviceWidthChanged) Q_PROPERTY(int deviceHeight WRITE setDeviceHeight READ deviceHeight NOTIFY deviceHeightChanged) - Q_PROPERTY(double devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY devicePixelRatioChanged) + Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY devicePixelRatioChanged) Q_PROPERTY(QWebNavigationHistory* navigationHistory READ navigationHistory CONSTANT FINAL) @@ -312,8 +312,8 @@ public: void setDeviceWidth(int); int deviceHeight() const; void setDeviceHeight(int); - double devicePixelRatio() const; - void setDevicePixelRatio(double); + qreal devicePixelRatio() const; + void setDevicePixelRatio(qreal); QList<QUrl> userScripts() const; void setUserScripts(const QList<QUrl>& userScripts); QUrl remoteInspectorUrl() const; diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h index d8a88f8c9..d1d3d9e88 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h @@ -21,13 +21,13 @@ #ifndef qquickwebview_p_p_h #define qquickwebview_p_p_h +#include "PageViewportController.h" +#include "PageViewportControllerClient.h" #include "QtPageClient.h" #include "QtWebPageUIClient.h" #include "QtWebUndoController.h" - #include "qquickwebview_p.h" #include "qquickwebpage_p.h" - #include <QtCore/QElapsedTimer> #include <QtCore/QObject> #include <QtCore/QScopedPointer> @@ -39,7 +39,7 @@ namespace WebKit { class DownloadProxy; class DrawingAreaProxy; class QtDialogRunner; -class QtViewportHandler; +class PageViewportControllerClientQt; class QtWebContext; class QtWebError; class QtWebPageLoadClient; @@ -87,7 +87,7 @@ public: int loadProgress() const { return m_loadProgress; } void setNeedsDisplay(); - virtual WebKit::QtViewportHandler* viewportHandler() { return 0; } + WebKit::PageViewportController* viewportController() const { return m_pageViewportController.data(); } virtual void updateViewportSize() { } void updateTouchViewportSize(); @@ -128,7 +128,7 @@ public: WebCore::IntSize viewSize() const; void didReceiveMessageFromNavigatorQtObject(const String& message); virtual void pageDidRequestScroll(const QPoint& pos) { } - virtual void didChangeContentsSize(const QSize& newSize) { } + virtual void didChangeContentsSize(const QSize& newSize); void processDidCrash(); void didRelaunchProcess(); PassOwnPtr<WebKit::DrawingAreaProxy> createDrawingAreaProxy(); @@ -170,7 +170,9 @@ protected: QScopedPointer<QQuickWebPage> pageView; QQuickWebView* q_ptr; - QScopedPointer<WebKit::QtViewportHandler> m_viewportHandler; + QScopedPointer<WebKit::PageViewportController> m_pageViewportController; + QScopedPointer<WebKit::PageViewportControllerClientQt> m_pageViewportControllerClient; + FlickableAxisLocker axisLocker; QQmlComponent* alertDialog; @@ -190,6 +192,7 @@ protected: bool m_navigatorQtObjectEnabled; bool m_renderToOffscreenBuffer; bool m_allowAnyHTTPSCertificateForLocalHost; + qreal m_customDevicePixelRatio; WTF::String m_iconUrl; int m_loadProgress; WTF::String m_currentUrl; @@ -211,13 +214,11 @@ class QQuickWebViewFlickablePrivate : public QQuickWebViewPrivate { Q_DECLARE_PUBLIC(QQuickWebView) public: QQuickWebViewFlickablePrivate(QQuickWebView* viewport); - virtual ~QQuickWebViewFlickablePrivate(); virtual void initialize(WKContextRef contextRef = 0, WKPageGroupRef pageGroupRef = 0); virtual void onComponentComplete(); virtual void didChangeViewportProperties(const WebCore::ViewportAttributes&); - virtual WebKit::QtViewportHandler* viewportHandler() { return m_viewportHandler.data(); } virtual void updateViewportSize(); virtual void pageDidRequestScroll(const QPoint& pos); diff --git a/Source/WebKit2/UIProcess/API/qt/qwebkittest.cpp b/Source/WebKit2/UIProcess/API/qt/qwebkittest.cpp index 1c39a53cd..a8a9c686b 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebkittest.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qwebkittest.cpp @@ -21,7 +21,7 @@ #include "config.h" #include "qwebkittest_p.h" -#include "QtViewportHandler.h" +#include "PageViewportControllerClientQt.h" #include "qquickwebview_p_p.h" #include <QMutableListIterator> #include <QTouchEvent> @@ -137,51 +137,42 @@ QSize QWebKitTest::contentsSize() const return QSize(m_webViewPrivate->pageView->contentsSize().toSize()); } -QVariant QWebKitTest::contentsScale() const +static inline QJsonObject toJsonObject(const QSizeF& sizeF) { - if (QtViewportHandler* viewport = m_webViewPrivate->viewportHandler()) - return viewport->currentCSSScale(); - return 1.0; + QJsonObject result; + result.insert(QLatin1String("width"), sizeF.width()); + result.insert(QLatin1String("height"), sizeF.height()); + return result; } -QVariant QWebKitTest::devicePixelRatio() const +QJsonObject QWebKitTest::viewport() const { - if (QtViewportHandler* viewport = m_webViewPrivate->viewportHandler()) - return viewport->m_devicePixelRatio; - return 1.0; -} - -QVariant QWebKitTest::initialScale() const -{ - if (QtViewportHandler* viewport = m_webViewPrivate->viewportHandler()) - return viewport->m_rawAttributes.initialScale; - return 1.0; + QJsonObject viewportData; + if (const PageViewportController* const viewportHandler = m_webViewPrivate->viewportController()) { + viewportData.insert(QLatin1String("layoutSize"), toJsonObject(viewportHandler->contentsLayoutSize())); + viewportData.insert(QLatin1String("isScalable"), viewportHandler->allowsUserScaling()); + viewportData.insert(QLatin1String("minimumScale"), viewportHandler->minimumContentsScale()); + viewportData.insert(QLatin1String("maximumScale"), viewportHandler->maximumContentsScale()); + } else { + viewportData.insert(QLatin1String("initialScale"), 1.0); + viewportData.insert(QLatin1String("layoutSize"), toJsonObject(QSizeF())); + viewportData.insert(QLatin1String("isScalable"), false); + viewportData.insert(QLatin1String("minimumScale"), 1.0); + viewportData.insert(QLatin1String("maximumScale"), 1.0); + } + return viewportData; } -QVariant QWebKitTest::minimumScale() const +QVariant QWebKitTest::devicePixelRatio() const { - if (QtViewportHandler* viewport = m_webViewPrivate->viewportHandler()) - return viewport->m_minimumScale; + if (const PageViewportController* const viewport = m_webViewPrivate->viewportController()) + return viewport->devicePixelRatio(); return 1.0; } -QVariant QWebKitTest::maximumScale() const +QVariant QWebKitTest::contentsScale() const { - if (QtViewportHandler* viewport = m_webViewPrivate->viewportHandler()) - return viewport->m_maximumScale; + if (const PageViewportController* const viewport = m_webViewPrivate->viewportController()) + return viewport->currentContentsScale(); return 1.0; } - -QVariant QWebKitTest::isScalable() const -{ - if (QtViewportHandler* viewport = m_webViewPrivate->viewportHandler()) - return !!viewport->m_rawAttributes.userScalable; - return false; -} - -QVariant QWebKitTest::layoutSize() const -{ - if (QtViewportHandler* viewport = m_webViewPrivate->viewportHandler()) - return QSizeF(viewport->m_rawAttributes.layoutSize); - return QSizeF(); -} diff --git a/Source/WebKit2/UIProcess/API/qt/qwebkittest_p.h b/Source/WebKit2/UIProcess/API/qt/qwebkittest_p.h index 3754f169a..bfabb69fb 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebkittest_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qwebkittest_p.h @@ -24,6 +24,7 @@ #include "qwebkitglobal.h" #include "qquickwebview_p.h" +#include <QtCore/QJsonObject> #include <QtCore/QObject> #include <QtCore/QPointer> #include <QtCore/QSize> @@ -40,17 +41,14 @@ class QWEBKIT_EXPORT QWebKitTest : public QObject { Q_PROPERTY(QVariant contentsScale READ contentsScale NOTIFY contentsScaleChanged) - Q_PROPERTY(QVariant devicePixelRatio READ devicePixelRatio NOTIFY viewportChanged) - Q_PROPERTY(QVariant initialScale READ initialScale NOTIFY viewportChanged) - Q_PROPERTY(QVariant isScalable READ isScalable NOTIFY viewportChanged) - Q_PROPERTY(QVariant maximumScale READ maximumScale NOTIFY viewportChanged) - Q_PROPERTY(QVariant minimumScale READ minimumScale NOTIFY viewportChanged) - Q_PROPERTY(QVariant layoutSize READ layoutSize NOTIFY viewportChanged) + Q_PROPERTY(QVariant devicePixelRatio READ devicePixelRatio NOTIFY devicePixelRatioChanged) + Q_PROPERTY(QJsonObject viewport READ viewport NOTIFY viewportChanged) Q_SIGNALS: void contentsSizeChanged(); void contentsScaleChanged(); void contentsScaleCommitted(); + void devicePixelRatioChanged(); void viewportChanged(); public Q_SLOTS: @@ -68,11 +66,7 @@ public: QVariant contentsScale() const; QVariant devicePixelRatio() const; - QVariant initialScale() const; - QVariant isScalable() const; - QVariant layoutSize() const; - QVariant maximumScale() const; - QVariant minimumScale() const; + QJsonObject viewport() const; private: QQuickWebViewPrivate* m_webViewPrivate; diff --git a/Source/WebKit2/UIProcess/API/qt/qwebpreferences.cpp b/Source/WebKit2/UIProcess/API/qt/qwebpreferences.cpp index e66f368c5..e27f51264 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebpreferences.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qwebpreferences.cpp @@ -71,6 +71,10 @@ bool QWebPreferencesPrivate::testAttribute(QWebPreferencesPrivate::WebAttribute return WKPreferencesGetCSSCustomFilterEnabled(preferencesRef()); #endif #endif +#if ENABLE(WEB_AUDIO) + case WebAudioEnabled: + return WKPreferencesGetWebAudioEnabled(preferencesRef()); +#endif default: ASSERT_NOT_REACHED(); return false; @@ -124,6 +128,11 @@ void QWebPreferencesPrivate::setAttribute(QWebPreferencesPrivate::WebAttribute a break; #endif #endif +#if ENABLE(WEB_AUDIO) + case WebAudioEnabled: + WKPreferencesSetWebAudioEnabled(preferencesRef(), enable); + break; +#endif default: ASSERT_NOT_REACHED(); } @@ -513,6 +522,25 @@ void QWebPreferences::setWebGLEnabled(bool enable) #endif } +bool QWebPreferences::webAudioEnabled() const +{ +#if ENABLE(WEB_AUDIO) + return d->testAttribute(QWebPreferencesPrivate::WebAudioEnabled); +#else + return false; +#endif +} + +void QWebPreferences::setWebAudioEnabled(bool enable) +{ +#if ENABLE(WEB_AUDIO) + d->setAttribute(QWebPreferencesPrivate::WebAudioEnabled, enable); + emit webAudioEnabledChanged(); +#else + UNUSED_PARAM(enable); +#endif +} + WKPreferencesRef QWebPreferencesPrivate::preferencesRef() const { WKPageGroupRef pageGroupRef = toAPI(webViewPrivate->webPageProxy->pageGroup()); diff --git a/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p.h b/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p.h index 8618f4fc3..373df7504 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p.h @@ -44,6 +44,7 @@ public: Q_PROPERTY(bool frameFlatteningEnabled READ frameFlatteningEnabled WRITE setFrameFlatteningEnabled NOTIFY frameFlatteningEnabledChanged FINAL) Q_PROPERTY(bool developerExtrasEnabled READ developerExtrasEnabled WRITE setDeveloperExtrasEnabled NOTIFY developerExtrasEnabledChanged FINAL) Q_PROPERTY(bool webGLEnabled READ webGLEnabled WRITE setWebGLEnabled NOTIFY webGLEnabledChanged FINAL) + Q_PROPERTY(bool webAudioEnabled READ webAudioEnabled WRITE setWebAudioEnabled NOTIFY webAudioEnabledChanged FINAL) Q_PROPERTY(QString standardFontFamily READ standardFontFamily WRITE setStandardFontFamily NOTIFY standardFontFamilyChanged FINAL) Q_PROPERTY(QString fixedFontFamily READ fixedFontFamily WRITE setFixedFontFamily NOTIFY fixedFontFamilyChanged FINAL) @@ -95,6 +96,9 @@ public: bool webGLEnabled() const; void setWebGLEnabled(bool enable); + bool webAudioEnabled() const; + void setWebAudioEnabled(bool enable); + QString standardFontFamily() const; void setStandardFontFamily(const QString& family); @@ -136,6 +140,7 @@ Q_SIGNALS: void frameFlatteningEnabledChanged(); void developerExtrasEnabledChanged(); void webGLEnabledChanged(); + void webAudioEnabledChanged(); void standardFontFamilyChanged(); void fixedFontFamilyChanged(); diff --git a/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p_p.h b/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p_p.h index 004500c90..c606bbe89 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p_p.h @@ -40,7 +40,8 @@ public: DnsPrefetchEnabled, DeveloperExtrasEnabled, WebGLEnabled, - CSSCustomFilterEnabled + CSSCustomFilterEnabled, + WebAudioEnabled }; enum FontFamily { diff --git a/Source/WebKit2/UIProcess/API/qt/raw/qrawwebview.cpp b/Source/WebKit2/UIProcess/API/qt/raw/qrawwebview.cpp index 6250348a6..0a7a684cf 100644 --- a/Source/WebKit2/UIProcess/API/qt/raw/qrawwebview.cpp +++ b/Source/WebKit2/UIProcess/API/qt/raw/qrawwebview.cpp @@ -185,7 +185,7 @@ PassRefPtr<WebKit::WebContextMenuProxy> QRawWebViewPrivate::createContextMenuPro } #if ENABLE(INPUT_TYPE_COLOR) -PassRefPtr<WebKit::WebColorChooserProxy> QRawWebViewPrivate::createColorChooserProxy(WebKit::WebPageProxy*, const WebCore::Color& intialColor) +PassRefPtr<WebKit::WebColorChooserProxy> QRawWebViewPrivate::createColorChooserProxy(WebKit::WebPageProxy*, const WebCore::Color& intialColor, const WebCore::IntRect&) { notImplemented(); return PassRefPtr<WebKit::WebColorChooserProxy>(); @@ -240,7 +240,10 @@ PassOwnPtr<WebKit::DrawingAreaProxy> QRawWebViewPrivate::createDrawingAreaProxy( } QRawWebViewPrivate::QRawWebViewPrivate(WebKit::WebContext* context, WebKit::WebPageGroup* pageGroup, QRawWebViewClient* client) - : m_client(client) + : m_focused(false) + , m_visible(false) + , m_active(false) + , m_client(client) , m_webPageProxy(context->createWebPage(this, pageGroup)) { m_webPageProxy->pageGroup()->preferences()->setForceCompositingMode(true); @@ -325,14 +328,20 @@ QSize QRawWebView::size() const void QRawWebView::setSize(const QSize& size) { - d->m_size = size; - d->m_webPageProxy->setViewportSize(size); - - WebKit::DrawingAreaProxy* drawingArea = d->m_webPageProxy->drawingArea(); if (!drawingArea) return; + if (d->m_webPageProxy->useFixedLayout()) + d->m_webPageProxy->setViewportSize(size); + else { + WebKit::LayerTreeCoordinatorProxy* coordinator = drawingArea->layerTreeCoordinatorProxy(); + if (!coordinator) + return; + coordinator->setContentsSize(WebCore::FloatSize(size.width(), size.height())); + } + + d->m_size = size; drawingArea->setSize(d->m_size, WebCore::IntSize()); drawingArea->setVisibleContentsRect(WebCore::IntRect(WebCore::IntPoint(), d->m_size), 1 /*scale*/, WebCore::FloatPoint()); diff --git a/Source/WebKit2/UIProcess/API/qt/raw/qrawwebview_p_p.h b/Source/WebKit2/UIProcess/API/qt/raw/qrawwebview_p_p.h index 0a4bf5a9e..55bc85ba0 100644 --- a/Source/WebKit2/UIProcess/API/qt/raw/qrawwebview_p_p.h +++ b/Source/WebKit2/UIProcess/API/qt/raw/qrawwebview_p_p.h @@ -25,8 +25,10 @@ #ifndef qrawwebview_p_p_h #define qrawwebview_p_p_h +#include "FindIndicator.h" #include "PageClient.h" #include "WebContextMenuProxy.h" +#include "WebEditCommandProxy.h" #include "WebPopupMenuProxy.h" #include "qrawwebview_p.h" @@ -87,7 +89,7 @@ public: virtual PassRefPtr<WebKit::WebContextMenuProxy> createContextMenuProxy(WebKit::WebPageProxy* webPageProxy); #if ENABLE(INPUT_TYPE_COLOR) - virtual PassRefPtr<WebKit::WebColorChooserProxy> createColorChooserProxy(WebKit::WebPageProxy*, const WebCore::Color& intialColor); + virtual PassRefPtr<WebKit::WebColorChooserProxy> createColorChooserProxy(WebKit::WebPageProxy*, const WebCore::Color& intialColor, const WebCore::IntRect&); #endif QRawWebViewPrivate(WebKit::WebContext*, WebKit::WebPageGroup*, QRawWebViewClient*); diff --git a/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.h b/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.h index 2262a5f1a..95b005f3a 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.h +++ b/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.h @@ -30,7 +30,7 @@ #include <QObject> #include <QtQuick/qquickitem.h> -class QWEBKIT_EXPORT ByteArrayTestData : public QObject { +class ByteArrayTestData : public QObject { Q_OBJECT Q_PROPERTY(QVariant latin1Data READ latin1Data) Q_PROPERTY(QVariant utf8Data READ utf8Data) diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_devicePixelRatio.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_devicePixelRatio.qml new file mode 100644 index 000000000..0442b53c9 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_devicePixelRatio.qml @@ -0,0 +1,62 @@ +import QtQuick 2.0 +import QtTest 1.0 +import QtWebKit 3.0 +import QtWebKit.experimental 1.0 +import "../common" + + +TestWebView { + id: webView + property variant lastResult + width: 400 + height: 300 + focus: true + + SignalSpy { + id: resultSpy + target: webView + signalName: "lastResultChanged" + } + + TestCase { + name: "DevicePixelRatio" + + function init() { + resultSpy.clear() + webView.lastResult = null + } + + function test_devicePixelRatio() { + resultSpy.clear() + webView.url = Qt.resolvedUrl("../common/test1.html"); + webView.experimental.devicePixelRatio = 2.0 + verify(webView.waitForLoadSucceeded()) + + webView.experimental.evaluateJavaScript( + "(function() { return window.devicePixelRatio })()", + function(result) { + webView.lastResult = result + }) + + resultSpy.wait() + compare(webView.lastResult, 2.0) + compare(webView.lastResult, webView.experimental.devicePixelRatio) + } + + function test_devicePixelRatioMediaQuery() { + resultSpy.clear() + webView.url = Qt.resolvedUrl("../common/test2.html"); + webView.experimental.devicePixelRatio = 2.0 + verify(webView.waitForLoadSucceeded()) + + webView.experimental.evaluateJavaScript( + "(function() { return window.matchMedia(\"(-webkit-device-pixel-ratio: 2)\").matches })()", + function(result) { + webView.lastResult = result + }) + + resultSpy.wait() + verify(webView.lastResult) + } + } +} diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_doubleTapToZoom.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_doubleTapToZoom.qml index b2a860e73..691455708 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_doubleTapToZoom.qml +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_doubleTapToZoom.qml @@ -13,8 +13,6 @@ Item { property variant result - experimental.test.onContentsScaleCommitted: scaleChanged() - property variant content: "data:text/html," + "<head>" + " <meta name='viewport' content='width=device-width'>" + @@ -26,7 +24,6 @@ Item { "</body>" signal resultReceived - signal scaleChanged } SignalSpy { @@ -37,8 +34,8 @@ Item { SignalSpy { id: scaleSpy - target: webView - signalName: "scaleChanged" + target: webView.experimental.test + signalName: "contentsScaleCommitted" } TestCase { @@ -67,8 +64,8 @@ Item { var result; webView.experimental.evaluateJavaScript( - "document.getElementById('" + id + "').getBoundingClientRect();", - function(rect) { webView.resultReceived(); result = rect }); + "JSON.stringify(document.getElementById('" + id + "').getBoundingClientRect());", + function(rect) { webView.resultReceived(); result = JSON.parse(rect); }); resultSpy.wait(); return result; } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_fitToView.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_fitToView.qml index febd948b8..f12da5de8 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_fitToView.qml +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_fitToView.qml @@ -13,8 +13,6 @@ Item { property variant result - experimental.test.onContentsScaleCommitted: scaleChanged() - property variant content: "data:text/html," + "<head>" + " <meta name='viewport' content='width=device-width'>" + @@ -24,7 +22,6 @@ Item { "</body>" signal resultReceived - signal scaleChanged } SignalSpy { @@ -35,8 +32,8 @@ Item { SignalSpy { id: scaleSpy - target: webView - signalName: "scaleChanged" + target: webView.experimental.test + signalName: "contentsScaleCommitted" } TestCase { diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_wheelEventHandling.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_wheelEventHandling.qml index d24312610..1fc1559ab 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_wheelEventHandling.qml +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_wheelEventHandling.qml @@ -42,5 +42,16 @@ Item { // The check below will fail if the previous position was not restored after reload. verify(position == webView.contentY) } + + function test_wheelScrollEventAfterReload() { + scrollSpy.clear() + webView.reload() + verify(webView.waitForLoadSucceeded()) + var centerPoint = Qt.point(webView.width / 2, webView.height / 2) + test.wheelEvent(webView, centerPoint.x, centerPoint.y, -500); + // The signal spy below will time out if the wheel event did not scroll the content. + scrollSpy.wait() + } } + } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qrawwebview/tst_qrawwebview.cpp b/Source/WebKit2/UIProcess/API/qt/tests/qrawwebview/tst_qrawwebview.cpp index 93d669cee..0338ecff6 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qrawwebview/tst_qrawwebview.cpp +++ b/Source/WebKit2/UIProcess/API/qt/tests/qrawwebview/tst_qrawwebview.cpp @@ -150,7 +150,7 @@ class tst_qrawwebview : public QObject { Q_OBJECT public: tst_qrawwebview() - : m_resourceDir(QString::fromAscii(TESTS_SOURCE_DIR "/html/resources")) + : m_resourceDir(QString::fromLatin1(TESTS_SOURCE_DIR "/html/resources")) , m_baseUrl(QUrl::fromLocalFile(TESTS_SOURCE_DIR "/html").toString()) { } diff --git a/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.cpp b/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.cpp index 6b0de7f25..e6f582f22 100644 --- a/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.cpp +++ b/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.cpp @@ -66,9 +66,9 @@ void LayerTreeCoordinatorProxy::updateTileForLayer(int layerID, int tileID, cons { RefPtr<ShareableSurface> surface; #if USE(GRAPHICS_SURFACE) - int token = updateInfo.surfaceHandle.graphicsSurfaceToken(); + uint64_t token = updateInfo.surfaceHandle.graphicsSurfaceToken(); if (token) { - HashMap<uint32_t, RefPtr<ShareableSurface> >::iterator it = m_surfaces.find(token); + HashMap<uint64_t, RefPtr<ShareableSurface> >::iterator it = m_surfaces.find(token); if (it == m_surfaces.end()) { surface = ShareableSurface::create(updateInfo.surfaceHandle); m_surfaces.add(token, surface); diff --git a/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.h b/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.h index ed71dfe94..65a9f5e99 100644 --- a/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.h +++ b/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeCoordinatorProxy.h @@ -88,7 +88,7 @@ protected: float m_lastSentScale; WebCore::FloatPoint m_lastSentTrajectoryVector; #if USE(GRAPHICS_SURFACE) - HashMap<uint32_t, RefPtr<ShareableSurface> > m_surfaces; + HashMap<uint64_t, RefPtr<ShareableSurface> > m_surfaces; #endif }; diff --git a/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeRenderer.cpp b/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeRenderer.cpp index 481b9f74b..b94c66b9d 100644 --- a/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeRenderer.cpp +++ b/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeRenderer.cpp @@ -66,7 +66,7 @@ private: } }; -void LayerTreeRenderer::callOnMainTread(const Function<void()>& function) +void LayerTreeRenderer::dispatchOnMainThread(const Function<void()>& function) { if (isMainThread()) function(); @@ -397,7 +397,7 @@ void LayerTreeRenderer::flushLayerChanges() commitTileOperations(); // The pending tiles state is on its way for the screen, tell the web process to render the next one. - callOnMainThread(bind(&LayerTreeRenderer::renderNextFrame, this)); + dispatchOnMainThread(bind(&LayerTreeRenderer::renderNextFrame, this)); } void LayerTreeRenderer::renderNextFrame() @@ -458,7 +458,7 @@ void LayerTreeRenderer::purgeGLResources() setActive(false); - callOnMainThread(bind(&LayerTreeRenderer::purgeBackingStores, this)); + dispatchOnMainThread(bind(&LayerTreeRenderer::purgeBackingStores, this)); } void LayerTreeRenderer::setAnimatedOpacity(uint32_t id, float opacity) diff --git a/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeRenderer.h b/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeRenderer.h index 5706a4ccd..4e45678e6 100644 --- a/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeRenderer.h +++ b/Source/WebKit2/UIProcess/CoordinatedGraphics/LayerTreeRenderer.h @@ -104,7 +104,7 @@ private: virtual bool showDebugBorders(const WebCore::GraphicsLayer*) const { return false; } virtual bool showRepaintCounter(const WebCore::GraphicsLayer*) const { return false; } void paintContents(const WebCore::GraphicsLayer*, WebCore::GraphicsContext&, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect&) { } - void callOnMainTread(const Function<void()>&); + void dispatchOnMainThread(const Function<void()>&); void adjustPositionForFixedLayers(); typedef HashMap<WebLayerID, WebCore::GraphicsLayer*> LayerMap; diff --git a/Source/WebKit2/UIProcess/Downloads/DownloadProxy.cpp b/Source/WebKit2/UIProcess/Downloads/DownloadProxy.cpp index 2ba13e03c..42d07379f 100644 --- a/Source/WebKit2/UIProcess/Downloads/DownloadProxy.cpp +++ b/Source/WebKit2/UIProcess/Downloads/DownloadProxy.cpp @@ -65,7 +65,7 @@ void DownloadProxy::cancel() if (!m_webContext) return; - // FIXME (Multi-WebProcess): Downloads shouldn't be handled in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/12239483> Downloads shouldn't be handled in the web process. m_webContext->sendToAllProcesses(Messages::WebProcess::CancelDownload(m_downloadID)); } @@ -98,7 +98,8 @@ void DownloadProxy::didReceiveAuthenticationChallenge(const AuthenticationChalle if (!m_webContext) return; - // FIXME (Multi-WebProcess): Get rid of deprecatedSharedProcess. + // FIXME (Multi-WebProcess): <rdar://problem/12239483> Downloads shouldn't be handled in the web process. + // Once this is fixed, remove WebContext::deprecatedSharedProcess(). RefPtr<AuthenticationChallengeProxy> authenticationChallengeProxy = AuthenticationChallengeProxy::create(authenticationChallenge, challengeID, m_webContext->deprecatedSharedProcess()); m_webContext->downloadClient().didReceiveAuthenticationChallenge(m_webContext, this, authenticationChallengeProxy.get()); } @@ -194,7 +195,7 @@ void DownloadProxy::startTransfer(const String& filename) if (!m_webContext) return; - // FIXME (Multi-WebProcess): Downloads shouldn't be handled in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/12239483> Downloads shouldn't be handled in the web process. m_webContext->sendToAllProcesses(Messages::WebProcess::StartTransfer(m_downloadID, filename)); } #endif diff --git a/Source/WebKit2/UIProcess/InspectorServer/WebInspectorServer.cpp b/Source/WebKit2/UIProcess/InspectorServer/WebInspectorServer.cpp index ecb171bb4..66d644734 100644 --- a/Source/WebKit2/UIProcess/InspectorServer/WebInspectorServer.cpp +++ b/Source/WebKit2/UIProcess/InspectorServer/WebInspectorServer.cpp @@ -142,7 +142,7 @@ bool WebInspectorServer::didReceiveWebSocketUpgradeHTTPRequest(WebSocketServerCo String path = request->url(); // NOTE: Keep this in sync with WebCore/inspector/front-end/inspector.js. - DEFINE_STATIC_LOCAL(const String, inspectorWebSocketConnectionPathPrefix, ("/devtools/page/")); + DEFINE_STATIC_LOCAL(const String, inspectorWebSocketConnectionPathPrefix, (ASCIILiteral("/devtools/page/"))); // Unknown path requested. if (!path.startsWith(inspectorWebSocketConnectionPathPrefix)) diff --git a/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerClient.h b/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerClient.h index e7be3abb7..448486877 100644 --- a/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerClient.h +++ b/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerClient.h @@ -28,13 +28,10 @@ #if ENABLE(INSPECTOR_SERVER) +#include <WebCore/HTTPRequest.h> #include <wtf/PassRefPtr.h> #include <wtf/text/WTFString.h> -namespace WebCore { -class HTTPRequest; -} - namespace WebKit { class WebSocketServerConnection; diff --git a/Source/WebKit2/UIProcess/InspectorServer/qt/WebInspectorServerQt.cpp b/Source/WebKit2/UIProcess/InspectorServer/qt/WebInspectorServerQt.cpp index 8de0f932d..c13fa4cfc 100644 --- a/Source/WebKit2/UIProcess/InspectorServer/qt/WebInspectorServerQt.cpp +++ b/Source/WebKit2/UIProcess/InspectorServer/qt/WebInspectorServerQt.cpp @@ -34,7 +34,7 @@ namespace WebKit { static String remoteInspectorPagePath() { - DEFINE_STATIC_LOCAL(String, pagePath, ("/webkit/inspector/inspector.html?page=")); + DEFINE_STATIC_LOCAL(String, pagePath, (ASCIILiteral("/webkit/inspector/inspector.html?page="))); return pagePath; } diff --git a/Source/WebKit2/UIProcess/Launcher/mac/ProcessLauncherMac.mm b/Source/WebKit2/UIProcess/Launcher/mac/ProcessLauncherMac.mm index fddf8502d..ec7d9e1d4 100644 --- a/Source/WebKit2/UIProcess/Launcher/mac/ProcessLauncherMac.mm +++ b/Source/WebKit2/UIProcess/Launcher/mac/ProcessLauncherMac.mm @@ -105,10 +105,13 @@ static void launchXPCService(const ProcessLauncher::LaunchOptions&, const Enviro // Insert a send right so we can send to it. mach_port_insert_right(mach_task_self(), listeningPort, listeningPort, MACH_MSG_TYPE_MAKE_SEND); + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + CString clientIdentifier = bundleIdentifier ? String([[NSBundle mainBundle] bundleIdentifier]).utf8() : *_NSGetProgname(); + xpc_object_t bootStrapMessage = xpc_dictionary_create(0, 0, 0); xpc_dictionary_set_string(bootStrapMessage, "message-name", "bootstrap"); - xpc_dictionary_set_string(bootStrapMessage, "framework-executable-path", [[[NSBundle bundleWithIdentifier:@"com.apple.WebKit2"] executablePath] fileSystemRepresentation]); xpc_dictionary_set_mach_send(bootStrapMessage, "server-port", listeningPort); + xpc_dictionary_set_string(bootStrapMessage, "client-identifier", clientIdentifier.data()); that->ref(); @@ -222,11 +225,14 @@ void ProcessLauncher::launchProcess() RetainPtr<CFStringRef> cfLocalization(AdoptCF, WKCopyCFLocalizationPreferredName(NULL)); CString localization = String(cfLocalization.get()).utf8(); - + + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + CString clientIdentifier = bundleIdentifier ? String([[NSBundle mainBundle] bundleIdentifier]).utf8() : *_NSGetProgname(); + // Make a unique, per pid, per process launcher web process service name. CString serviceName = String::format("com.apple.WebKit.WebProcess-%d-%p", getpid(), this).utf8(); - const char* args[] = { [processAppExecutablePath fileSystemRepresentation], frameworkExecutablePath, "-type", processTypeAsString(m_launchOptions.processType), "-servicename", serviceName.data(), "-localization", localization.data(), 0 }; + const char* args[] = { [processAppExecutablePath fileSystemRepresentation], frameworkExecutablePath, "-type", processTypeAsString(m_launchOptions.processType), "-servicename", serviceName.data(), "-localization", localization.data(), "-client-identifier", clientIdentifier.data(), 0 }; // Register ourselves. kern_return_t kr = bootstrap_register2(bootstrap_port, const_cast<char*>(serviceName.data()), listeningPort, 0); diff --git a/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp b/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp index f099d6283..3cacf04db 100644 --- a/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp +++ b/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp @@ -38,6 +38,12 @@ #include <QtCore/qglobal.h> #include <WebCore/NotImplemented.h> #include <WebCore/RunLoop.h> +#include <wtf/HashSet.h> +#include <wtf/PassRefPtr.h> +#include <wtf/Threading.h> +#include <wtf/text/WTFString.h> + +#if defined(Q_OS_UNIX) #include <errno.h> #include <fcntl.h> #include <runtime/InitializeThreading.h> @@ -45,16 +51,17 @@ #include <sys/resource.h> #include <sys/socket.h> #include <unistd.h> -#include <wtf/HashSet.h> -#include <wtf/PassRefPtr.h> -#include <wtf/Threading.h> -#include <wtf/text/WTFString.h> +#endif #if defined(Q_OS_LINUX) #include <sys/prctl.h> #include <signal.h> #endif +#if OS(WINDOWS) +#include <windows.h> +#endif + #if OS(DARWIN) #include <mach/mach_init.h> #include <servers/bootstrap.h> @@ -62,7 +69,8 @@ extern "C" kern_return_t bootstrap_register2(mach_port_t, name_t, mach_port_t, uint64_t); #endif -#if defined(SOCK_SEQPACKET) && !defined(Q_OS_MACX) +// for QNX we need SOCK_DGRAM, see https://bugs.webkit.org/show_bug.cgi?id=95553 +#if defined(SOCK_SEQPACKET) && !defined(Q_OS_MACX) && !OS(QNX) #define SOCKET_TYPE SOCK_SEQPACKET #else #define SOCKET_TYPE SOCK_DGRAM @@ -126,6 +134,15 @@ void ProcessLauncher::launchProcess() ASSERT_UNUSED(kr, kr == KERN_SUCCESS); commandLine = commandLine.arg(serviceName); +#elif OS(WINDOWS) + CoreIPC::Connection::Identifier connector, clientIdentifier; + if (!CoreIPC::Connection::createServerAndClientIdentifiers(connector, clientIdentifier)) { + // FIXME: What should we do here? + ASSERT_NOT_REACHED(); + } + commandLine = commandLine.arg(qulonglong(clientIdentifier)); + // Ensure that the child process inherits the client identifier. + ::SetHandleInformation(clientIdentifier, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); #else int sockets[2]; if (socketpair(AF_UNIX, SOCKET_TYPE, 0, sockets) == -1) { @@ -152,7 +169,7 @@ void ProcessLauncher::launchProcess() webProcess->setProcessChannelMode(QProcess::ForwardedChannels); webProcess->start(commandLine); -#if !OS(DARWIN) +#if OS(UNIX) && !OS(DARWIN) // Don't expose the web socket to possible future web processes while (fcntl(sockets[0], F_SETFD, FD_CLOEXEC) == -1) { if (errno != EINTR) { @@ -174,7 +191,9 @@ void ProcessLauncher::launchProcess() return; } +#if OS(UNIX) setpriority(PRIO_PROCESS, webProcess->pid(), 10); +#endif RunLoop::main()->dispatch(bind(&WebKit::ProcessLauncher::didFinishLaunchingProcess, this, webProcess, connector)); } diff --git a/Source/WebKit2/UIProcess/PageClient.h b/Source/WebKit2/UIProcess/PageClient.h index a343ae610..ebf5cd16f 100644 --- a/Source/WebKit2/UIProcess/PageClient.h +++ b/Source/WebKit2/UIProcess/PageClient.h @@ -180,7 +180,7 @@ public: virtual PassRefPtr<WebContextMenuProxy> createContextMenuProxy(WebPageProxy*) = 0; #if ENABLE(INPUT_TYPE_COLOR) - virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& initialColor) = 0; + virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& initialColor, const WebCore::IntRect&) = 0; #endif virtual void setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut, bool animate) = 0; diff --git a/Source/WebKit2/UIProcess/PageViewportController.cpp b/Source/WebKit2/UIProcess/PageViewportController.cpp new file mode 100644 index 000000000..71ec685c2 --- /dev/null +++ b/Source/WebKit2/UIProcess/PageViewportController.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2011, 2012 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2011 Benjamin Poulain <benjamin@webkit.org> + * + * 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 program 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 program; 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 "PageViewportController.h" + +#include "PageViewportControllerClient.h" +#include "WebPageProxy.h" +#include <WebCore/FloatRect.h> +#include <WebCore/FloatSize.h> +#include <wtf/MathExtras.h> + +namespace WebKit { + +static inline float bound(float min, float value, float max) +{ + return clampTo<float>(value, min, max); +} + +bool fuzzyCompare(float a, float b, float epsilon) +{ + return std::abs(a - b) < epsilon; +} + +FloatPoint boundPosition(const FloatPoint minPosition, const FloatPoint& position, const FloatPoint& maxPosition) +{ + return FloatPoint(bound(minPosition.x(), position.x(), maxPosition.x()), bound(minPosition.y(), position.y(), maxPosition.y())); +} + +ViewportUpdateDeferrer::ViewportUpdateDeferrer(PageViewportController* PageViewportController, SuspendContentFlag suspendContentFlag) + : m_controller(PageViewportController) +{ + m_controller->m_activeDeferrerCount++; + + // There is no need to suspend content for immediate updates + // only during animations or longer gestures. + if (suspendContentFlag == DeferUpdateAndSuspendContent) + m_controller->suspendContent(); +} + +ViewportUpdateDeferrer::~ViewportUpdateDeferrer() +{ + if (--(m_controller->m_activeDeferrerCount)) + return; + + m_controller->resumeContent(); + + // Make sure that tiles all around the viewport will be requested. + m_controller->syncVisibleContents(); +} + +PageViewportController::PageViewportController(WebKit::WebPageProxy* proxy, PageViewportControllerClient* client) + : m_webPageProxy(proxy) + , m_client(client) + , m_allowsUserScaling(false) + , m_minimumScale(1) + , m_maximumScale(1) + , m_devicePixelRatio(1) + , m_activeDeferrerCount(0) + , m_hasSuspendedContent(false) + , m_hadUserInteraction(false) + , m_effectiveScale(1) +{ + // Initializing Viewport Raw Attributes to avoid random negative scale factors + // if there is a race condition between the first layout and setting the viewport attributes for the first time. + m_rawAttributes.initialScale = 1; + m_rawAttributes.minimumScale = m_minimumScale; + m_rawAttributes.maximumScale = m_maximumScale; + m_rawAttributes.userScalable = m_allowsUserScaling; + + ASSERT(m_client); + m_client->setController(this); +} + +FloatRect PageViewportController::convertToViewport(const FloatRect& cssRect) const +{ + return FloatRect( + convertToViewport(cssRect.x()), + convertToViewport(cssRect.y()), + convertToViewport(cssRect.width()), + convertToViewport(cssRect.height()) + ); +} + +float PageViewportController::innerBoundedContentsScale(float cssScale) const +{ + return bound(m_minimumScale, cssScale, m_maximumScale); +} + +float PageViewportController::outerBoundedContentsScale(float cssScale) const +{ + if (m_allowsUserScaling) { + // Bounded by [0.1, 10.0] like the viewport meta code in WebCore. + float hardMin = std::max<float>(0.1, 0.5 * m_minimumScale); + float hardMax = std::min<float>(10, 2 * m_maximumScale); + return bound(hardMin, cssScale, hardMax); + } + return innerBoundedContentsScale(cssScale); +} + +void PageViewportController::didChangeContentsSize(const IntSize& newSize) +{ + if (m_viewportSize.isEmpty() || newSize.isEmpty()) + return; + + m_contentsSize = newSize; + + float minimumScale = WebCore::computeMinimumScaleFactorForContentContained(m_rawAttributes, WebCore::roundedIntSize(m_viewportSize), newSize); + + if (!fuzzyCompare(minimumScale, m_rawAttributes.minimumScale, 0.001)) { + m_minimumScale = minimumScale; + + if (!m_hadUserInteraction && !hasSuspendedContent()) + m_client->setContentsScale(convertToViewport(minimumScale), true /* isInitialScale */); + + m_client->didChangeViewportAttributes(); + } + + m_client->didChangeContentsSize(); +} + +void PageViewportController::pageDidRequestScroll(const IntPoint& cssPosition) +{ + // Ignore the request if suspended. Can only happen due to delay in event delivery. + if (m_activeDeferrerCount) + return; + + FloatRect endPosRange = positionRangeForContentAtScale(m_effectiveScale); + FloatPoint endPosition(cssPosition); + endPosition.scale(m_effectiveScale, m_effectiveScale); + endPosition = boundPosition(endPosRange.minXMinYCorner(), endPosition, endPosRange.maxXMaxYCorner()); + + m_client->setContentsPosition(endPosition); +} + +void PageViewportController::setViewportSize(const FloatSize& newSize) +{ + if (newSize.isEmpty()) + return; + + m_viewportSize = newSize; + + // Let the WebProcess know about the new viewport size, so that + // it can resize the content accordingly. + m_webPageProxy->setViewportSize(roundedIntSize(newSize)); + + syncVisibleContents(); +} + +void PageViewportController::setVisibleContentsRect(const FloatRect& visibleContentsRect, float viewportScale, const FloatPoint& trajectoryVector) +{ + m_visibleContentsRect = visibleContentsRect; + m_effectiveScale = viewportScale; + syncVisibleContents(trajectoryVector); +} + +void PageViewportController::syncVisibleContents(const FloatPoint& trajectoryVector) +{ + DrawingAreaProxy* const drawingArea = m_webPageProxy->drawingArea(); + if (!drawingArea || m_viewportSize.isEmpty() || m_contentsSize.isEmpty() || m_visibleContentsRect.isEmpty()) + return; + + drawingArea->setVisibleContentsRect(m_visibleContentsRect, m_effectiveScale, trajectoryVector); + + m_client->didChangeVisibleContents(); +} + +void PageViewportController::didChangeViewportAttributes(const WebCore::ViewportAttributes& newAttributes) +{ + if (newAttributes.layoutSize.isEmpty()) + return; + + m_rawAttributes = newAttributes; + WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(m_rawAttributes); + + m_devicePixelRatio = m_webPageProxy->deviceScaleFactor(); + m_allowsUserScaling = !!m_rawAttributes.userScalable; + m_minimumScale = m_rawAttributes.minimumScale; + m_maximumScale = m_rawAttributes.maximumScale; + + m_client->didChangeViewportAttributes(); +} + +void PageViewportController::suspendContent() +{ + if (m_hasSuspendedContent) + return; + + m_hasSuspendedContent = true; + m_webPageProxy->suspendActiveDOMObjectsAndAnimations(); +} + +void PageViewportController::resumeContent() +{ + if (!m_rawAttributes.layoutSize.isEmpty() && m_rawAttributes.initialScale > 0) { + m_hadUserInteraction = false; + m_client->setContentsScale(convertToViewport(innerBoundedContentsScale(m_rawAttributes.initialScale)), /* isInitialScale */ true); + m_rawAttributes.initialScale = -1; // Mark used. + } + + m_client->didResumeContent(); + + if (!m_hasSuspendedContent) + return; + + m_hasSuspendedContent = false; + m_webPageProxy->resumeActiveDOMObjectsAndAnimations(); +} + +FloatRect PageViewportController::positionRangeForContentAtScale(float viewportScale) const +{ + const FloatSize contentSize = m_contentsSize * viewportScale; + + const float horizontalRange = contentSize.width() - m_viewportSize.width(); + const float verticalRange = contentSize.height() - m_viewportSize.height(); + + return FloatRect(0, 0, horizontalRange, verticalRange); +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/PageViewportController.h b/Source/WebKit2/UIProcess/PageViewportController.h new file mode 100644 index 000000000..0746ff1df --- /dev/null +++ b/Source/WebKit2/UIProcess/PageViewportController.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2011, 2012 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2011 Benjamin Poulain <benjamin@webkit.org> + * + * 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 program 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 program; 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 PageViewportController_h +#define PageViewportController_h + +#include <WebCore/FloatPoint.h> +#include <WebCore/FloatRect.h> +#include <WebCore/FloatSize.h> +#include <WebCore/ViewportArguments.h> + +namespace WebCore { +class IntPoint; +class IntSize; +} + +using namespace WebCore; + +namespace WebKit { + +class WebPageProxy; +class PageViewportController; +class PageViewportControllerClient; + +// When interacting with the content, either by animating or by the hand of the user, +// it is important to ensure smooth animations of at least 60fps in order to give a +// good user experience. +// +// In order to do this we need to get rid of unknown factors. These include device +// sensors (geolocation, orientation updates etc), CSS3 animations, JavaScript +// exectution, sub resource loads etc. +// We do this by sending suspend and resume notifications to the web process. +// +// For this purpose the ViewportUpdateDeferrer guard can be used when interacting +// with or animating the content to scope suspend / resume and defer update +// notifications. +// +// If something should only be executed when the content is suspended, it is possible +// to check for that using ASSERT(hasSuspendedContent()). + +class ViewportUpdateDeferrer { +public: + enum SuspendContentFlag { DeferUpdate, DeferUpdateAndSuspendContent }; + ViewportUpdateDeferrer(PageViewportController*, SuspendContentFlag = DeferUpdate); + ~ViewportUpdateDeferrer(); + +private: + PageViewportController* const m_controller; +}; + +class PageViewportController { + WTF_MAKE_NONCOPYABLE(PageViewportController); + +public: + PageViewportController(WebKit::WebPageProxy*, PageViewportControllerClient*); + virtual ~PageViewportController() { } + + void suspendContent(); + void resumeContent(); + + FloatRect positionRangeForContentAtScale(float viewportScale) const; + + float convertFromViewport(float value) const { return value / m_devicePixelRatio; } + float convertToViewport(float value) const { return value * m_devicePixelRatio; } + FloatRect convertToViewport(const FloatRect&) const; + + float innerBoundedContentsScale(float) const; + float outerBoundedContentsScale(float) const; + + bool hasSuspendedContent() const { return m_hasSuspendedContent; } + bool hadUserInteraction() const { return m_hadUserInteraction; } + bool allowsUserScaling() const { return m_allowsUserScaling; } + + FloatSize contentsLayoutSize() const { return m_rawAttributes.layoutSize; } + float devicePixelRatio() const { return m_devicePixelRatio; } + float minimumContentsScale() const { return m_minimumScale; } + float maximumContentsScale() const { return m_maximumScale; } + float currentContentsScale() const { return convertFromViewport(m_effectiveScale); } + + void setHadUserInteraction(bool didUserInteract) { m_hadUserInteraction = didUserInteract; } + + // Notifications to the WebProcess. + void setViewportSize(const FloatSize& newSize); + void setVisibleContentsRect(const FloatRect& visibleContentsRect, float viewportScale, const FloatPoint& trajectoryVector = FloatPoint::zero()); + + // Notifications from the WebProcess. + void didChangeContentsSize(const IntSize& newSize); + void didChangeViewportAttributes(const ViewportAttributes&); + void pageDidRequestScroll(const IntPoint& cssPosition); + +private: + void syncVisibleContents(const FloatPoint &trajectoryVector = FloatPoint::zero()); + + WebPageProxy* const m_webPageProxy; + PageViewportControllerClient* m_client; + + ViewportAttributes m_rawAttributes; + + bool m_allowsUserScaling; + float m_minimumScale; + float m_maximumScale; + float m_devicePixelRatio; + + int m_activeDeferrerCount; + bool m_hasSuspendedContent; + bool m_hadUserInteraction; + + FloatSize m_viewportSize; + FloatSize m_contentsSize; + FloatRect m_visibleContentsRect; + float m_effectiveScale; // Should always be cssScale * devicePixelRatio. + + friend class ViewportUpdateDeferrer; +}; + +bool fuzzyCompare(float, float, float epsilon); +FloatPoint boundPosition(const FloatPoint minPosition, const FloatPoint& position, const FloatPoint& maxPosition); + +} // namespace WebKit + +#endif // PageViewportController_h diff --git a/Source/WebKit2/UIProcess/PageViewportControllerClient.h b/Source/WebKit2/UIProcess/PageViewportControllerClient.h new file mode 100644 index 000000000..6a50b4217 --- /dev/null +++ b/Source/WebKit2/UIProcess/PageViewportControllerClient.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 program 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 program; 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 PageViewportControllerClient_h +#define PageViewportControllerClient_h + +#include <wtf/Noncopyable.h> + +namespace WebKit { + +class PageViewportController; + +class PageViewportControllerClient { + WTF_MAKE_NONCOPYABLE(PageViewportControllerClient); +public: + PageViewportControllerClient() { } + virtual ~PageViewportControllerClient() { } + + virtual void setContentsPosition(const WebCore::FloatPoint& localPoint) = 0; + virtual void setContentsScale(float localScale, bool treatAsInitialValue) = 0; + + virtual void didResumeContent() = 0; + virtual void didChangeContentsSize() = 0; + virtual void didChangeVisibleContents() = 0; + virtual void didChangeViewportAttributes() = 0; + + virtual void setController(PageViewportController*) = 0; +}; + +} // namespace WebKit + +#endif // PageViewportControllerClient_h diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp index 12abf6dc2..7c53b695e 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp @@ -47,6 +47,8 @@ using namespace WebCore; namespace WebKit { +static const double shutdownTimeout = 15; + PassRefPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo) { return adoptRef(new PluginProcessProxy(PluginProcessManager, pluginInfo)); @@ -211,6 +213,8 @@ void PluginProcessProxy::didFinishLaunching(ProcessLauncher*, CoreIPC::Connectio parameters.pluginPath = m_pluginInfo.path; + parameters.terminationTimeout = shutdownTimeout; + platformInitializePluginProcess(parameters); // Initialize the plug-in host process. diff --git a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp index 553ea727b..a26bbbdb8 100644 --- a/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp +++ b/Source/WebKit2/UIProcess/Plugins/WebPluginSiteDataManager.cpp @@ -170,8 +170,7 @@ void WebPluginSiteDataManager::getSitesWithData(PassRefPtr<ArrayCallback> prpCal for (size_t i = 0; i < plugins.size(); ++i) pluginPaths.append(plugins[i].path); - // FIXME (Multi-WebProcess): When multi-process is enabled, we must always use a plug-in process for this, - // so this code should just be removed. + ASSERT(m_webContext->processModel() == ProcessModelSharedSecondaryProcess); // Plugin process is required for multiple WebProcess mode. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebProcess::GetSitesWithPluginData(pluginPaths, callbackID)); #endif } @@ -233,8 +232,7 @@ void WebPluginSiteDataManager::clearSiteData(ImmutableArray* sites, uint64_t fla for (size_t i = 0; i < plugins.size(); ++i) pluginPaths.append(plugins[i].path); - // FIXME (Multi-WebProcess): When multi-process is enabled, we must always use a plug-in process for this, - // so this code should just be removed. + ASSERT(m_webContext->processModel() == ProcessModelSharedSecondaryProcess); // Plugin process is required for multiple WebProcess mode. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebProcess::ClearPluginSiteData(pluginPaths, sitesVector, flags, maxAgeInSeconds, callbackID)); #endif } diff --git a/Source/WebKit2/UIProcess/VisitedLinkProvider.cpp b/Source/WebKit2/UIProcess/VisitedLinkProvider.cpp index 912d05fd7..7ecae847c 100644 --- a/Source/WebKit2/UIProcess/VisitedLinkProvider.cpp +++ b/Source/WebKit2/UIProcess/VisitedLinkProvider.cpp @@ -40,16 +40,15 @@ static const int VisitedLinkTableMaxLoad = 2; VisitedLinkProvider::VisitedLinkProvider(WebContext* context) : m_context(context) , m_visitedLinksPopulated(false) - , m_webProcessHasVisitedLinkState(false) , m_keyCount(0) , m_tableSize(0) , m_pendingVisitedLinksTimer(RunLoop::main(), this, &VisitedLinkProvider::pendingVisitedLinksTimerFired) { } -void VisitedLinkProvider::processDidFinishLaunching() +void VisitedLinkProvider::processDidFinishLaunching(WebProcessProxy* process) { - m_webProcessHasVisitedLinkState = false; + m_processesWithoutVisitedLinkState.add(process); if (m_keyCount) m_pendingVisitedLinksTimer.startOneShot(0); @@ -70,9 +69,10 @@ void VisitedLinkProvider::addVisitedLink(LinkHash linkHash) m_pendingVisitedLinksTimer.startOneShot(0); } -void VisitedLinkProvider::processDidClose() +void VisitedLinkProvider::processDidClose(WebProcessProxy* process) { - m_pendingVisitedLinksTimer.stop(); + m_processesWithVisitedLinkState.remove(process); + m_processesWithoutVisitedLinkState.remove(process); } static unsigned nextPowerOf2(unsigned v) @@ -111,18 +111,26 @@ void VisitedLinkProvider::pendingVisitedLinksTimerFired() m_pendingVisitedLinks.clear(); unsigned currentTableSize = m_tableSize; + + // Upper bound on needed size - some of the links may be duplicates, in which case we could have done with less. unsigned newTableSize = tableSizeForKeyCount(m_keyCount + pendingVisitedLinks.size()); + // Never decrease table size when adding to it, to avoid unneeded churn. + newTableSize = std::max(currentTableSize, newTableSize); + // Links that were added. Vector<WebCore::LinkHash> addedVisitedLinks; + // VisitedLinkTable remains internally consistent when adding, so it's OK to modify it in place + // even if a web process is accessing it at the same time. if (currentTableSize != newTableSize) { - // Create a new table. RefPtr<SharedMemory> newTableMemory = SharedMemory::create(newTableSize * sizeof(LinkHash)); // We failed to create the shared memory. - if (!newTableMemory) + if (!newTableMemory) { + LOG_ERROR("Could not allocate shared memory for visited link table"); return; + } memset(newTableMemory->data(), 0, newTableMemory->size()); @@ -156,27 +164,36 @@ void VisitedLinkProvider::pendingVisitedLinksTimerFired() m_keyCount += pendingVisitedLinks.size(); - if (!m_webProcessHasVisitedLinkState || currentTableSize != newTableSize) { - // Send the new visited link table. - + + for (HashSet<WebProcessProxy*>::iterator iter = m_processesWithVisitedLinkState.begin(); iter != m_processesWithVisitedLinkState.end(); ++iter) { + WebProcessProxy* process = *iter; + if (currentTableSize != newTableSize) { + // In the rare case of needing to resize the table, we'll bypass the VisitedLinkStateChanged optimization, + // and unconditionally use AllVisitedLinkStateChanged for the process. + m_processesWithoutVisitedLinkState.add(process); + continue; + } + + if (addedVisitedLinks.size() <= 20) + process->send(Messages::WebProcess::VisitedLinkStateChanged(addedVisitedLinks), 0); + else + process->send(Messages::WebProcess::AllVisitedLinkStateChanged(), 0); + } + + for (HashSet<WebProcessProxy*>::iterator iter = m_processesWithoutVisitedLinkState.begin(); iter != m_processesWithoutVisitedLinkState.end(); ++iter) { + WebProcessProxy* process = *iter; + SharedMemory::Handle handle; if (!m_table.sharedMemory()->createHandle(handle, SharedMemory::ReadOnly)) return; - // FIXME (Multi-WebProcess): Encoding a handle will null it out so we need to create a new - // handle for every process. Maybe the ArgumentEncoder should handle this. - m_context->sendToAllProcesses(Messages::WebProcess::SetVisitedLinkTable(handle)); - } - - // We now need to let the web process know that we've added links. - if (m_webProcessHasVisitedLinkState && addedVisitedLinks.size() <= 20) { - m_context->sendToAllProcesses(Messages::WebProcess::VisitedLinkStateChanged(addedVisitedLinks)); - return; + process->send(Messages::WebProcess::SetVisitedLinkTable(handle), 0); + process->send(Messages::WebProcess::AllVisitedLinkStateChanged(), 0); + + m_processesWithVisitedLinkState.add(process); } - // Just recalculate all the visited links. - m_context->sendToAllProcesses(Messages::WebProcess::AllVisitedLinkStateChanged()); - m_webProcessHasVisitedLinkState = true; + m_processesWithoutVisitedLinkState.clear(); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/VisitedLinkProvider.h b/Source/WebKit2/UIProcess/VisitedLinkProvider.h index 461c5ac94..e0e531025 100644 --- a/Source/WebKit2/UIProcess/VisitedLinkProvider.h +++ b/Source/WebKit2/UIProcess/VisitedLinkProvider.h @@ -35,6 +35,7 @@ namespace WebKit { class WebContext; +class WebProcessProxy; class VisitedLinkProvider { WTF_MAKE_NONCOPYABLE(VisitedLinkProvider); @@ -43,15 +44,16 @@ public: void addVisitedLink(WebCore::LinkHash); - void processDidFinishLaunching(); - void processDidClose(); + void processDidFinishLaunching(WebProcessProxy*); + void processDidClose(WebProcessProxy*); private: void pendingVisitedLinksTimerFired(); WebContext* m_context; bool m_visitedLinksPopulated; - bool m_webProcessHasVisitedLinkState; + HashSet<WebProcessProxy*> m_processesWithVisitedLinkState; + HashSet<WebProcessProxy*> m_processesWithoutVisitedLinkState; unsigned m_keyCount; unsigned m_tableSize; diff --git a/Source/WebKit2/UIProcess/WebApplicationCacheManagerProxy.cpp b/Source/WebKit2/UIProcess/WebApplicationCacheManagerProxy.cpp index 5ea62cdc3..f43c819fd 100644 --- a/Source/WebKit2/UIProcess/WebApplicationCacheManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebApplicationCacheManagerProxy.cpp @@ -69,7 +69,7 @@ void WebApplicationCacheManagerProxy::getApplicationCacheOrigins(PassRefPtr<Arra uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - // FIXME (Multi-WebProcess): The application cache shouldn't be stored in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/12239765> Make manipulating cache information work with per-tab WebProcess. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebApplicationCacheManager::GetApplicationCacheOrigins(callbackID)); } @@ -86,13 +86,13 @@ void WebApplicationCacheManagerProxy::deleteEntriesForOrigin(WebSecurityOrigin* securityOriginData.host = origin->host(); securityOriginData.port = origin->port(); - // FIXME (Multi-WebProcess): The application cache shouldn't be stored in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/12239765> Make manipulating cache information work with per-tab WebProcess. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebApplicationCacheManager::DeleteEntriesForOrigin(securityOriginData)); } void WebApplicationCacheManagerProxy::deleteAllEntries() { - // FIXME (Multi-WebProcess): The application cache shouldn't be stored in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/12239765> Make manipulating cache information work with per-tab WebProcess. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebApplicationCacheManager::DeleteAllEntries()); } diff --git a/Source/WebKit2/UIProcess/WebContext.cpp b/Source/WebKit2/UIProcess/WebContext.cpp index b5bbea4cd..0003387d0 100644 --- a/Source/WebKit2/UIProcess/WebContext.cpp +++ b/Source/WebKit2/UIProcess/WebContext.cpp @@ -86,6 +86,8 @@ using namespace WebCore; namespace WebKit { +static const double sharedSecondaryProcessShutdownTimeout = 60; + DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webContextCounter, ("WebContext")); PassRefPtr<WebContext> WebContext::create(const String& injectedBundlePath) @@ -110,6 +112,7 @@ const Vector<WebContext*>& WebContext::allContexts() WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePath) : m_processModel(processModel) + , m_haveInitialEmptyProcess(false) , m_defaultPageGroup(WebPageGroup::create()) , m_injectedBundlePath(injectedBundlePath) , m_visitedLinkProvider(this) @@ -255,6 +258,21 @@ void WebContext::initializeDownloadClient(const WKContextDownloadClient* client) m_downloadClient.initialize(client); } +void WebContext::setProcessModel(ProcessModel processModel) +{ + // Guard against API misuse. + if (!m_processes.isEmpty()) + CRASH(); + +#if !ENABLE(PLUGIN_PROCESS) + // Plugin process is required for multiple web process mode. + if (processModel != ProcessModelSharedSecondaryProcess) + CRASH(); +#endif + + m_processModel = processModel; +} + WebProcessProxy* WebContext::deprecatedSharedProcess() { ASSERT(m_processModel == ProcessModelSharedSecondaryProcess); @@ -295,21 +313,25 @@ PassRefPtr<WebProcessProxy> WebContext::createNewWebProcess() WebProcessCreationParameters parameters; - if (!injectedBundlePath().isEmpty()) { - parameters.injectedBundlePath = injectedBundlePath(); + parameters.injectedBundlePath = injectedBundlePath(); + if (!parameters.injectedBundlePath.isEmpty()) SandboxExtension::createHandle(parameters.injectedBundlePath, SandboxExtension::ReadOnly, parameters.injectedBundlePathExtensionHandle); - } - parameters.shouldTrackVisitedLinks = m_historyClient.shouldTrackVisitedLinks(); - parameters.cacheModel = m_cacheModel; - parameters.languages = userPreferredLanguages(); parameters.applicationCacheDirectory = applicationCacheDirectory(); + if (!parameters.applicationCacheDirectory.isEmpty()) + SandboxExtension::createHandle(parameters.applicationCacheDirectory, SandboxExtension::ReadWrite, parameters.applicationCacheDirectoryExtensionHandle); + parameters.databaseDirectory = databaseDirectory(); + if (!parameters.databaseDirectory.isEmpty()) + SandboxExtension::createHandle(parameters.databaseDirectory, SandboxExtension::ReadWrite, parameters.databaseDirectoryExtensionHandle); + parameters.localStorageDirectory = localStorageDirectory(); + if (!parameters.localStorageDirectory.isEmpty()) + SandboxExtension::createHandle(parameters.localStorageDirectory, SandboxExtension::ReadWrite, parameters.localStorageDirectoryExtensionHandle); -#if PLATFORM(MAC) - parameters.presenterApplicationPid = getpid(); -#endif + parameters.shouldTrackVisitedLinks = m_historyClient.shouldTrackVisitedLinks(); + parameters.cacheModel = m_cacheModel; + parameters.languages = userPreferredLanguages(); copyToVector(m_schemesToRegisterAsEmptyDocument, parameters.urlSchemesRegistererdAsEmptyDocument); copyToVector(m_schemesToRegisterAsSecure, parameters.urlSchemesRegisteredAsSecure); @@ -320,6 +342,8 @@ PassRefPtr<WebProcessProxy> WebContext::createNewWebProcess() parameters.iconDatabaseEnabled = !iconDatabasePath().isEmpty(); + parameters.terminationTimeout = (m_processModel == ProcessModelSharedSecondaryProcess) ? sharedSecondaryProcessShutdownTimeout : 0; + parameters.textCheckerState = TextChecker::state(); parameters.fullKeyboardAccessEnabled = WebProcessProxy::fullKeyboardAccessEnabled(); @@ -342,7 +366,7 @@ PassRefPtr<WebProcessProxy> WebContext::createNewWebProcess() pair<String, RefPtr<APIObject> >& message = m_pendingMessagesToPostToInjectedBundle[i]; process->deprecatedSend(InjectedBundleMessage::PostMessage, 0, CoreIPC::In(message.first, WebContextUserMessageEncoder(message.second.get()))); } - // FIXME (Multi-WebProcess): What does this mean in the brave new world? + // FIXME (Multi-WebProcess) (94368): What does this mean in the brave new world? m_pendingMessagesToPostToInjectedBundle.clear(); return process.release(); @@ -350,8 +374,13 @@ PassRefPtr<WebProcessProxy> WebContext::createNewWebProcess() void WebContext::warmInitialProcess() { - ASSERT(m_processes.isEmpty()); + if (m_haveInitialEmptyProcess) { + ASSERT(!m_processes.isEmpty()); + return; + } + m_processes.append(createNewWebProcess()); + m_haveInitialEmptyProcess = true; } void WebContext::enableProcessTermination() @@ -398,7 +427,7 @@ void WebContext::processDidFinishLaunching(WebProcessProxy* process) { ASSERT(m_processes.contains(process)); - m_visitedLinkProvider.processDidFinishLaunching(); + m_visitedLinkProvider.processDidFinishLaunching(process); // Sometimes the memorySampler gets initialized after process initialization has happened but before the process has finished launching // so check if it needs to be started here @@ -418,7 +447,15 @@ void WebContext::disconnectProcess(WebProcessProxy* process) { ASSERT(m_processes.contains(process)); - m_visitedLinkProvider.processDidClose(); + m_visitedLinkProvider.processDidClose(process); + + // FIXME (Multi-WebProcess): <rdar://problem/12239765> All the invalidation calls below are still necessary in multi-process mode, but they should only affect data structures pertaining to the process being disconnected. + // Clearing everything causes assertion failures, so it's less trouble to skip that for now. + if (m_processModel != ProcessModelSharedSecondaryProcess) { + RefPtr<WebProcessProxy> protect(process); + m_processes.remove(m_processes.find(process)); + return; + } // Invalidate all outstanding downloads. for (HashMap<uint64_t, RefPtr<DownloadProxy> >::iterator::Values it = m_downloads.begin().values(), end = m_downloads.end().values(); it != end; ++it) { @@ -457,7 +494,10 @@ void WebContext::disconnectProcess(WebProcessProxy* process) m_pluginSiteDataManager->invalidate(); #endif - // This can cause the web context to be destroyed. + // The vector may have the last reference to process proxy, which in turn may have the last reference to the context. + // Since vector elements are destroyed in place, we would recurse into WebProcessProxy destructor + // if it were invoked from Vector::remove(). RefPtr delays destruction until it's safe. + RefPtr<WebProcessProxy> protect(process); m_processes.remove(m_processes.find(process)); } @@ -469,8 +509,15 @@ PassRefPtr<WebPageProxy> WebContext::createWebPage(PageClient* pageClient, WebPa process = m_processes[0]; } else { // FIXME (Multi-WebProcess): Add logic for sharing a process. - process = createNewWebProcess(); - m_processes.append(process); + // <rdar://problem/12218164> window.open() should create pages in the same process. + // <rdar://problem/12239661> Consider limiting the number of web processes in per-tab process model + if (m_haveInitialEmptyProcess) { + process = m_processes.last(); + m_haveInitialEmptyProcess = false; + } else { + process = createNewWebProcess(); + m_processes.append(process); + } } if (!pageGroup) @@ -507,7 +554,7 @@ DownloadProxy* WebContext::download(WebPageProxy* initiatingPage, const Resource return download; } else { - // FIXME: (Multi-WebProcess): Implement. + // FIXME (Multi-WebProcess): <rdar://problem/12239483> Make downloading work. return 0; } } @@ -893,7 +940,7 @@ void WebContext::getWebCoreStatistics(PassRefPtr<DictionaryCallback> callback) m_processes[0]->send(Messages::WebProcess::GetWebCoreStatistics(callbackID), 0); } else { - // FIXME (Multi-WebProcess): Implement. + // FIXME (Multi-WebProcess): <rdar://problem/12239483> Make downloading work. callback->invalidate(); } } diff --git a/Source/WebKit2/UIProcess/WebContext.h b/Source/WebKit2/UIProcess/WebContext.h index a011461f4..a8ddc5f63 100644 --- a/Source/WebKit2/UIProcess/WebContext.h +++ b/Source/WebKit2/UIProcess/WebContext.h @@ -89,6 +89,7 @@ public: void initializeHistoryClient(const WKContextHistoryClient*); void initializeDownloadClient(const WKContextDownloadClient*); + void setProcessModel(ProcessModel); // Can only be called when there are no processes running. ProcessModel processModel() const { return m_processModel; } // FIXME (Multi-WebProcess): Remove. No code should assume that there is a shared process. @@ -276,6 +277,7 @@ private: ProcessModel m_processModel; Vector<RefPtr<WebProcessProxy> > m_processes; + bool m_haveInitialEmptyProcess; RefPtr<WebPageGroup> m_defaultPageGroup; diff --git a/Source/WebKit2/UIProcess/WebCookieManagerProxy.cpp b/Source/WebKit2/UIProcess/WebCookieManagerProxy.cpp index e7b4a6a8e..cc9b23eb6 100644 --- a/Source/WebKit2/UIProcess/WebCookieManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebCookieManagerProxy.cpp @@ -76,7 +76,7 @@ void WebCookieManagerProxy::getHostnamesWithCookies(PassRefPtr<ArrayCallback> pr uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - // FIXME (Multi-WebProcess): Cookies shouldn't be stored in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/12239765> Cookies shouldn't be stored in the web process. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebCookieManager::GetHostnamesWithCookies(callbackID)); } @@ -145,7 +145,8 @@ void WebCookieManagerProxy::getHTTPCookieAcceptPolicy(PassRefPtr<HTTPCookieAccep uint64_t callbackID = callback->callbackID(); m_httpCookieAcceptPolicyCallbacks.set(callbackID, callback.release()); - // FIXME (Multi-WebProcess): Cookies shouldn't be stored in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/12240189> Make cookie policies work with per-tab WebProcess. + // We can't ber asking all web processes for this information. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebCookieManager::GetHTTPCookieAcceptPolicy(callbackID)); } diff --git a/Source/WebKit2/UIProcess/WebDatabaseManagerProxy.cpp b/Source/WebKit2/UIProcess/WebDatabaseManagerProxy.cpp index 76db33686..b4331d45c 100644 --- a/Source/WebKit2/UIProcess/WebDatabaseManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebDatabaseManagerProxy.cpp @@ -40,49 +40,49 @@ namespace WebKit { String WebDatabaseManagerProxy::originKey() { - DEFINE_STATIC_LOCAL(String, key, ("WebDatabaseManagerOriginKey")); + DEFINE_STATIC_LOCAL(String, key, (ASCIILiteral("WebDatabaseManagerOriginKey"))); return key; } String WebDatabaseManagerProxy::originQuotaKey() { - DEFINE_STATIC_LOCAL(String, key, ("WebDatabaseManagerOriginQuotaKey")); + DEFINE_STATIC_LOCAL(String, key, (ASCIILiteral("WebDatabaseManagerOriginQuotaKey"))); return key; } String WebDatabaseManagerProxy::originUsageKey() { - DEFINE_STATIC_LOCAL(String, key, ("WebDatabaseManagerOriginUsageKey")); + DEFINE_STATIC_LOCAL(String, key, (ASCIILiteral("WebDatabaseManagerOriginUsageKey"))); return key; } String WebDatabaseManagerProxy::databaseDetailsKey() { - DEFINE_STATIC_LOCAL(String, key, ("WebDatabaseManagerDatabaseDetailsKey")); + DEFINE_STATIC_LOCAL(String, key, (ASCIILiteral("WebDatabaseManagerDatabaseDetailsKey"))); return key; } String WebDatabaseManagerProxy::databaseDetailsNameKey() { - DEFINE_STATIC_LOCAL(String, key, ("WebDatabaseManagerDatabaseDetailsNameKey")); + DEFINE_STATIC_LOCAL(String, key, (ASCIILiteral("WebDatabaseManagerDatabaseDetailsNameKey"))); return key; } String WebDatabaseManagerProxy::databaseDetailsDisplayNameKey() { - DEFINE_STATIC_LOCAL(String, key, ("WebDatabaseManagerDatabaseDetailsDisplayNameKey")); + DEFINE_STATIC_LOCAL(String, key, (ASCIILiteral("WebDatabaseManagerDatabaseDetailsDisplayNameKey"))); return key; } String WebDatabaseManagerProxy::databaseDetailsExpectedUsageKey() { - DEFINE_STATIC_LOCAL(String, key, ("WebDatabaseManagerDatabaseDetailsExpectedUsageKey")); + DEFINE_STATIC_LOCAL(String, key, (ASCIILiteral("WebDatabaseManagerDatabaseDetailsExpectedUsageKey"))); return key; } String WebDatabaseManagerProxy::databaseDetailsCurrentUsageKey() { - DEFINE_STATIC_LOCAL(String, key, ("WebDatabaseManagerDatabaseDetailsCurrentUsageKey")); + DEFINE_STATIC_LOCAL(String, key, (ASCIILiteral("WebDatabaseManagerDatabaseDetailsCurrentUsageKey"))); return key; } @@ -121,7 +121,7 @@ void WebDatabaseManagerProxy::getDatabasesByOrigin(PassRefPtr<ArrayCallback> prp uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - // FIXME (Multi-WebProcess): Databases shouldn't be stored in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/12239765> Databases shouldn't be stored in the web process. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebDatabaseManager::GetDatabasesByOrigin(callbackID)); } @@ -174,7 +174,7 @@ void WebDatabaseManagerProxy::getDatabaseOrigins(PassRefPtr<ArrayCallback> prpCa uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - // FIXME (Multi-WebProcess): Databases shouldn't be stored in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/12239765> Databases shouldn't be stored in the web process. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebDatabaseManager::GetDatabaseOrigins(callbackID)); } @@ -197,25 +197,25 @@ void WebDatabaseManagerProxy::didGetDatabaseOrigins(const Vector<String>& origin void WebDatabaseManagerProxy::deleteDatabaseWithNameForOrigin(const String& databaseIdentifier, WebSecurityOrigin* origin) { - // FIXME (Multi-WebProcess): Databases shouldn't be stored in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/7855696> Databases shouldn't be stored in the web process. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebDatabaseManager::DeleteDatabaseWithNameForOrigin(databaseIdentifier, origin->databaseIdentifier())); } void WebDatabaseManagerProxy::deleteDatabasesForOrigin(WebSecurityOrigin* origin) { - // FIXME (Multi-WebProcess): Databases shouldn't be stored in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/7855696> Databases shouldn't be stored in the web process. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebDatabaseManager::DeleteDatabasesForOrigin(origin->databaseIdentifier())); } void WebDatabaseManagerProxy::deleteAllDatabases() { - // FIXME (Multi-WebProcess): Databases shouldn't be stored in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/7855696> Databases shouldn't be stored in the web process. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebDatabaseManager::DeleteAllDatabases()); } void WebDatabaseManagerProxy::setQuotaForOrigin(WebSecurityOrigin* origin, uint64_t quota) { - // FIXME (Multi-WebProcess): Databases shouldn't be stored in the web process. + // FIXME (Multi-WebProcess): <rdar://problem/7855696> Databases shouldn't be stored in the web process. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebDatabaseManager::SetQuotaForOrigin(origin->databaseIdentifier(), quota)); } diff --git a/Source/WebKit2/UIProcess/WebIconDatabase.cpp b/Source/WebKit2/UIProcess/WebIconDatabase.cpp index c0c70617b..41c2617bf 100644 --- a/Source/WebKit2/UIProcess/WebIconDatabase.cpp +++ b/Source/WebKit2/UIProcess/WebIconDatabase.cpp @@ -161,7 +161,7 @@ void WebIconDatabase::getLoadDecisionForIconURL(const String& iconURL, uint64_t return; if (!m_iconDatabaseImpl || !m_iconDatabaseImpl->isOpen() || iconURL.isEmpty()) { - // FIXME (Multi-WebProcess): We need to know which connection to send this message to. + // FIXME (Multi-WebProcess): <rdar://problem/12240223> We need to know which connection to send this message to. m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision(static_cast<int>(IconLoadNo), callbackID)); return; } @@ -176,7 +176,7 @@ void WebIconDatabase::getLoadDecisionForIconURL(const String& iconURL, uint64_t return; } - // FIXME (Multi-WebProcess): We need to know which connection to send this message to. + // FIXME (Multi-WebProcess): <rdar://problem/12240223> We need to know which connection to send this message to. m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision((int)decision, callbackID)); } @@ -269,7 +269,7 @@ void WebIconDatabase::didFinishURLImport() // Decisions should never be unknown after the inital import is complete ASSERT(decision != IconLoadUnknown); - // FIXME (Multi-WebProcess): We need to know which connection to send this message to. + // FIXME (Multi-WebProcess): <rdar://problem/12240223> We need to know which connection to send this message to. m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision(static_cast<int>(decision), i->first)); } diff --git a/Source/WebKit2/UIProcess/WebInspectorProxy.cpp b/Source/WebKit2/UIProcess/WebInspectorProxy.cpp index 52c0b74a6..4ef85f25a 100644 --- a/Source/WebKit2/UIProcess/WebInspectorProxy.cpp +++ b/Source/WebKit2/UIProcess/WebInspectorProxy.cpp @@ -329,7 +329,7 @@ void WebInspectorProxy::createInspectorPage(uint64_t& inspectorPageID, WebPageCr String url = inspectorPageURL(); if (m_isAttached) - url += "?docked=true"; + url.append("?docked=true"); m_page->process()->assumeReadAccessToBaseURL(inspectorBaseURL()); diff --git a/Source/WebKit2/UIProcess/WebKeyValueStorageManagerProxy.cpp b/Source/WebKit2/UIProcess/WebKeyValueStorageManagerProxy.cpp index 93b6fb914..8b3332aa5 100644 --- a/Source/WebKit2/UIProcess/WebKeyValueStorageManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebKeyValueStorageManagerProxy.cpp @@ -68,7 +68,7 @@ void WebKeyValueStorageManagerProxy::getKeyValueStorageOrigins(PassRefPtr<ArrayC uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - // FIXME (Multi-WebProcess): Should key-value storage be handled in the web process? + // FIXME (Multi-WebProcess): <rdar://problem/12239765> Should key-value storage be handled in the web process? m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebKeyValueStorageManager::GetKeyValueStorageOrigins(callbackID)); } @@ -85,13 +85,13 @@ void WebKeyValueStorageManagerProxy::deleteEntriesForOrigin(WebSecurityOrigin* o securityOriginData.host = origin->host(); securityOriginData.port = origin->port(); - // FIXME (Multi-WebProcess): Should key-value storage be handled in the web process? + // FIXME (Multi-WebProcess): <rdar://problem/12239765> Should key-value storage be handled in the web process? m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebKeyValueStorageManager::DeleteEntriesForOrigin(securityOriginData)); } void WebKeyValueStorageManagerProxy::deleteAllEntries() { - // FIXME (Multi-WebProcess): Should key-value storage be handled in the web process? + // FIXME (Multi-WebProcess): <rdar://problem/12239765> Should key-value storage be handled in the web process? m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebKeyValueStorageManager::DeleteAllEntries()); } diff --git a/Source/WebKit2/UIProcess/WebMediaCacheManagerProxy.cpp b/Source/WebKit2/UIProcess/WebMediaCacheManagerProxy.cpp index 3b034d86e..ce4a78c64 100644 --- a/Source/WebKit2/UIProcess/WebMediaCacheManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebMediaCacheManagerProxy.cpp @@ -67,8 +67,7 @@ void WebMediaCacheManagerProxy::getHostnamesWithMediaCache(PassRefPtr<ArrayCallb uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - // FIXME (Multi-WebProcess): When we're sending this to multiple processes, we need to aggregate the - // callback data when it comes back. + // FIXME (Multi-WebProcess): <rdar://problem/12239765> When we're sending this to multiple processes, we need to aggregate the callback data when it comes back. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebMediaCacheManager::GetHostnamesWithMediaCache(callbackID)); } diff --git a/Source/WebKit2/UIProcess/WebPageProxy.cpp b/Source/WebKit2/UIProcess/WebPageProxy.cpp index c88c6655a..cd0c6c9a6 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.cpp +++ b/Source/WebKit2/UIProcess/WebPageProxy.cpp @@ -897,7 +897,7 @@ void WebPageProxy::executeEditCommand(const String& commandName) if (!isValid()) return; - DEFINE_STATIC_LOCAL(String, ignoreSpellingCommandName, ("ignoreSpelling")); + DEFINE_STATIC_LOCAL(String, ignoreSpellingCommandName, (ASCIILiteral("ignoreSpelling"))); if (commandName == ignoreSpellingCommandName) ++m_pendingLearnOrIgnoreWordMessageCount; @@ -2707,11 +2707,11 @@ void WebPageProxy::needTouchEvents(bool needTouchEvents) #endif #if ENABLE(INPUT_TYPE_COLOR) -void WebPageProxy::showColorChooser(const WebCore::Color& initialColor) +void WebPageProxy::showColorChooser(const WebCore::Color& initialColor, const IntRect& elementRect) { ASSERT(!m_colorChooser); - m_colorChooser = m_pageClient->createColorChooserProxy(this, initialColor); + m_colorChooser = m_pageClient->createColorChooserProxy(this, initialColor, elementRect); } void WebPageProxy::setColorChooserColor(const WebCore::Color& color) @@ -2911,6 +2911,9 @@ void WebPageProxy::showPopupMenu(const IntRect& rect, uint64_t textDirection, co m_activePopupMenu = m_pageClient->createPopupMenuProxy(this); + if (!m_activePopupMenu) + return; + // Since showPopupMenu() can spin a nested run loop we need to turn off the responsiveness timer. m_process->responsivenessTimer()->stop(); @@ -2918,8 +2921,8 @@ void WebPageProxy::showPopupMenu(const IntRect& rect, uint64_t textDirection, co protectedActivePopupMenu->showPopupMenu(rect, static_cast<TextDirection>(textDirection), m_pageScaleFactor, items, data, selectedIndex); - // Since Qt doesn't use a nested mainloop the show the popup and get the answer, we need to keep the client pointer valid. -#if !PLATFORM(QT) + // Since Qt and Efl doesn't use a nested mainloop to show the popup and get the answer, we need to keep the client pointer valid. +#if !PLATFORM(QT) && !PLATFORM(EFL) protectedActivePopupMenu->invalidate(); #endif protectedActivePopupMenu = 0; @@ -2959,6 +2962,8 @@ void WebPageProxy::internalShowContextMenu(const IntPoint& menuLocation, const W } m_activeContextMenu = m_pageClient->createContextMenuProxy(this); + if (!m_activeContextMenu) + return; // Since showContextMenu() can spin a nested run loop we need to turn off the responsiveness timer. m_process->responsivenessTimer()->stop(); diff --git a/Source/WebKit2/UIProcess/WebPageProxy.h b/Source/WebKit2/UIProcess/WebPageProxy.h index 9a19a566b..a4026816d 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.h +++ b/Source/WebKit2/UIProcess/WebPageProxy.h @@ -99,6 +99,7 @@ namespace WebCore { class FloatRect; class IntSize; class ProtectionSpace; + class SharedBuffer; struct FileChooserSettings; struct TextAlternativeWithRange; struct TextCheckingResult; @@ -848,7 +849,7 @@ private: #endif #if ENABLE(INPUT_TYPE_COLOR) - void showColorChooser(const WebCore::Color& initialColor); + void showColorChooser(const WebCore::Color& initialColor, const WebCore::IntRect&); void setColorChooserColor(const WebCore::Color&); void endColorChooser(); void didChooseColor(const WebCore::Color&); diff --git a/Source/WebKit2/UIProcess/WebPageProxy.messages.in b/Source/WebKit2/UIProcess/WebPageProxy.messages.in index 7fa81be5a..2ac9d267f 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.messages.in +++ b/Source/WebKit2/UIProcess/WebPageProxy.messages.in @@ -88,7 +88,7 @@ messages -> WebPageProxy { #endif #if ENABLE(INPUT_TYPE_COLOR) - ShowColorChooser(WebCore::Color initialColor); + ShowColorChooser(WebCore::Color initialColor, WebCore::IntRect elementRect); SetColorChooserColor(WebCore::Color color); EndColorChooser(); #endif diff --git a/Source/WebKit2/UIProcess/WebResourceCacheManagerProxy.cpp b/Source/WebKit2/UIProcess/WebResourceCacheManagerProxy.cpp index 8c06bdc83..60bf1a1ba 100644 --- a/Source/WebKit2/UIProcess/WebResourceCacheManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebResourceCacheManagerProxy.cpp @@ -68,7 +68,7 @@ void WebResourceCacheManagerProxy::getCacheOrigins(PassRefPtr<ArrayCallback> prp uint64_t callbackID = callback->callbackID(); m_arrayCallbacks.set(callbackID, callback.release()); - // FIXME (Multi-WebProcess): When multi-process is enabled, we need to aggregate the callback data from all processes. + // FIXME (Multi-WebProcess): <rdar://problem/12239765> When multi-process is enabled, we need to aggregate the callback data from all processes. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebResourceCacheManager::GetCacheOrigins(callbackID)); } @@ -85,11 +85,13 @@ void WebResourceCacheManagerProxy::clearCacheForOrigin(WebSecurityOrigin* origin securityOrigin.host = origin->host(); securityOrigin.port = origin->port(); + // FIXME (Multi-WebProcess): <rdar://problem/12239765> There is no need to relaunch all processes. One process to take care of persistent cache is enough. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebResourceCacheManager::ClearCacheForOrigin(securityOrigin, cachesToClear)); } void WebResourceCacheManagerProxy::clearCacheForAllOrigins(ResourceCachesToClear cachesToClear) { + // FIXME (Multi-WebProcess): <rdar://problem/12239765> There is no need to relaunch all processes. One process to take care of persistent cache is enough. m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebResourceCacheManager::ClearCacheForAllOrigins(cachesToClear)); } diff --git a/Source/WebKit2/UIProcess/efl/WebFullScreenManagerProxyEfl.cpp b/Source/WebKit2/UIProcess/efl/WebFullScreenManagerProxyEfl.cpp index b295687c1..f000c152a 100644 --- a/Source/WebKit2/UIProcess/efl/WebFullScreenManagerProxyEfl.cpp +++ b/Source/WebKit2/UIProcess/efl/WebFullScreenManagerProxyEfl.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "WebFullScreenManagerProxy.h" +#include "ewk_view_private.h" #if ENABLE(FULLSCREEN_API) @@ -52,12 +53,22 @@ bool WebFullScreenManagerProxy::isFullScreen() void WebFullScreenManagerProxy::enterFullScreen() { - notImplemented(); + if (!m_webView) + return; + + willEnterFullScreen(); + ewk_view_full_screen_enter(m_webView); + didEnterFullScreen(); } void WebFullScreenManagerProxy::exitFullScreen() { - notImplemented(); + if (!m_webView) + return; + + willExitFullScreen(); + ewk_view_full_screen_exit(m_webView); + didExitFullScreen(); } void WebFullScreenManagerProxy::beganEnterFullScreen(const IntRect& initialFrame, const IntRect& finalFrame) diff --git a/Source/WebKit2/UIProcess/efl/WebInspectorProxyEfl.cpp b/Source/WebKit2/UIProcess/efl/WebInspectorProxyEfl.cpp index 2b1537e1b..538356610 100644 --- a/Source/WebKit2/UIProcess/efl/WebInspectorProxyEfl.cpp +++ b/Source/WebKit2/UIProcess/efl/WebInspectorProxyEfl.cpp @@ -29,6 +29,7 @@ #if ENABLE(INSPECTOR) #include "WebProcessProxy.h" +#include "ewk_view.h" #include "ewk_view_private.h" #include <WebCore/NotImplemented.h> #include <unistd.h> @@ -46,6 +47,7 @@ WebPageProxy* WebInspectorProxy::platformCreateInspectorPage() return 0; m_inspectorView = ewk_view_base_add(ecore_evas_get(m_inspectorWindow), toAPI(page()->process()->context()), toAPI(inspectorPageGroup())); + ewk_view_theme_set(m_inspectorView, TEST_THEME_DIR"/default.edj"); return ewk_view_page_get(m_inspectorView); } diff --git a/Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp b/Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp index e1eda1035..94dc44b31 100644 --- a/Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp +++ b/Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp @@ -28,6 +28,7 @@ #include "NotImplemented.h" #include "PageClientImpl.h" +#include "WebKitVersion.h" #include "WebPageMessages.h" #include "WebProcessProxy.h" @@ -51,16 +52,15 @@ String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent #else platform = "Unknown"; #endif - version = makeString(String::number(WEBKIT_USER_AGENT_MAJOR_VERSION), '.', - String::number(WEBKIT_USER_AGENT_MINOR_VERSION), '+'); + version = String::number(WEBKIT_MAJOR_VERSION) + '.' + String::number(WEBKIT_MINOR_VERSION) + '+'; struct utsname name; if (uname(&name) != -1) osVersion = WTF::String(name.sysname) + " " + WTF::String(name.machine); else osVersion = "Unknown"; - return makeString("Mozilla/5.0 (", platform, "; ", osVersion, ") AppleWebKit/", version) - + makeString(" (KHTML, like Gecko) Version/5.0 Safari/", version); + return "Mozilla/5.0 (" + platform + "; " + osVersion + ") AppleWebKit/" + version + + " (KHTML, like Gecko) Version/5.0 Safari/" + version; } void WebPageProxy::getEditorCommandsForKeyEvent(Vector<WTF::String>& commandsList) diff --git a/Source/WebKit2/UIProcess/efl/WebPopupMenuProxyEfl.cpp b/Source/WebKit2/UIProcess/efl/WebPopupMenuProxyEfl.cpp new file mode 100644 index 000000000..03d504ba4 --- /dev/null +++ b/Source/WebKit2/UIProcess/efl/WebPopupMenuProxyEfl.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT HOLDER OR + * 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 "WebPopupMenuProxyEfl.h" + +#include "NativeWebMouseEvent.h" +#include "WebPopupItem.h" +#include "ewk_view.h" +#include "ewk_view_private.h" +#include <wtf/text/CString.h> + +using namespace WebCore; + +namespace WebKit { + +WebPopupMenuProxyEfl::WebPopupMenuProxyEfl(Evas_Object* webView, WebPopupMenuProxy::Client* client) + : WebPopupMenuProxy(client) + , m_webView(webView) +{ +} + +void WebPopupMenuProxyEfl::showPopupMenu(const IntRect& rect, TextDirection textDirection, double pageScaleFactor, const Vector<WebPopupItem>& items, const PlatformPopupMenuData&, int32_t selectedIndex) +{ + ewk_view_popup_menu_request(m_webView, this, rect, textDirection, pageScaleFactor, items, selectedIndex); +} + +void WebPopupMenuProxyEfl::hidePopupMenu() +{ + ewk_view_popup_menu_close(m_webView); +} + +void WebPopupMenuProxyEfl::valueChanged(int newSelectedIndex) +{ + m_client->valueChangedForPopupMenu(this, newSelectedIndex); +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/efl/WebPopupMenuProxyEfl.h b/Source/WebKit2/UIProcess/efl/WebPopupMenuProxyEfl.h new file mode 100644 index 000000000..ab4074ab2 --- /dev/null +++ b/Source/WebKit2/UIProcess/efl/WebPopupMenuProxyEfl.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT HOLDER OR + * 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 WebPopupMenuProxyEfl_h +#define WebPopupMenuProxyEfl_h + +#include "WebPopupMenuProxy.h" + +typedef struct _Evas_Object Evas_Object; + +namespace WebCore { +class IntRect; +} + +namespace WebKit { + +class WebPageProxy; + +class WebPopupMenuProxyEfl : public WebPopupMenuProxy { +public: + static PassRefPtr<WebPopupMenuProxyEfl> create(Evas_Object* webView, WebPopupMenuProxy::Client* client) + { + return adoptRef(new WebPopupMenuProxyEfl(webView, client)); + } + + void showPopupMenu(const WebCore::IntRect&, WebCore::TextDirection, double pageScaleFactor, const Vector<WebPopupItem>&, const PlatformPopupMenuData&, int32_t selectedIndex); + void hidePopupMenu(); + + void valueChanged(int newSelectedIndex); + +private: + WebPopupMenuProxyEfl(Evas_Object*, WebPopupMenuProxy::Client*); + + Evas_Object* m_webView; +}; + +} // namespace WebKit + +#endif // WebPopupMenuProxyEfl_h diff --git a/Source/WebKit2/UIProcess/mac/WebContextMac.mm b/Source/WebKit2/UIProcess/mac/WebContextMac.mm index fcd004e23..8b7be9530 100644 --- a/Source/WebKit2/UIProcess/mac/WebContextMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebContextMac.mm @@ -75,24 +75,28 @@ String WebContext::applicationCacheDirectory() void WebContext::platformInitializeWebProcess(WebProcessCreationParameters& parameters) { + parameters.presenterApplicationPid = getpid(); + if (!omitPDFSupport()) { // We want to use a PDF view in the UI process for PDF MIME types. HashSet<String, CaseFoldingHash> mimeType = pdfAndPostScriptMIMETypes(); parameters.mimeTypesWithCustomRepresentation.appendRange(mimeType.begin(), mimeType.end()); } + parameters.parentProcessName = [[NSProcessInfo processInfo] processName]; + RetainPtr<CFStringRef> cachePath(AdoptCF, WKCopyFoundationCacheDirectory()); if (!cachePath) cachePath = reinterpret_cast<CFStringRef>(NSHomeDirectory()); - NSURLCache *urlCache = [NSURLCache sharedURLCache]; - - parameters.parentProcessName = [[NSProcessInfo processInfo] processName]; parameters.nsURLCachePath = [(NSString *)cachePath.get() stringByStandardizingPath]; + SandboxExtension::createHandle(parameters.nsURLCachePath, SandboxExtension::ReadWrite, parameters.nsURLCachePathExtensionHandle); + ASSERT(!parameters.nsURLCachePath.isEmpty()); + + NSURLCache *urlCache = [NSURLCache sharedURLCache]; parameters.nsURLCacheMemoryCapacity = [urlCache memoryCapacity]; parameters.nsURLCacheDiskCapacity = [urlCache diskCapacity]; - ASSERT(!parameters.nsURLCachePath.isEmpty()); #if ENABLE(PLUGIN_PROCESS) parameters.disablePluginProcessMessageTimeout = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitDisablePluginProcessMessageTimeout"]; @@ -110,6 +114,7 @@ void WebContext::platformInitializeWebProcess(WebProcessCreationParameters& para // FIXME: This should really be configurable; we shouldn't just blindly allow read access to the UI process bundle. parameters.uiProcessBundleResourcePath = [[NSBundle mainBundle] resourcePath]; + SandboxExtension::createHandle(parameters.uiProcessBundleResourcePath, SandboxExtension::ReadOnly, parameters.uiProcessBundleResourcePathExtensionHandle); parameters.uiProcessBundleIdentifier = String([[NSBundle mainBundle] bundleIdentifier]); diff --git a/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp b/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp new file mode 100644 index 000000000..3d134ea93 --- /dev/null +++ b/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.cpp @@ -0,0 +1,547 @@ +/* + * Copyright (C) 2011, 2012 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2011 Benjamin Poulain <benjamin@webkit.org> + * + * 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 program 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 program; 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 "PageViewportControllerClientQt.h" + +#include "qquickwebpage_p.h" +#include "qquickwebview_p.h" +#include "qwebkittest_p.h" +#include <QPointF> +#include <QTransform> +#include <QtQuick/qquickitem.h> +#include <WebCore/FloatRect.h> +#include <WebCore/FloatSize.h> + +namespace WebKit { + +static const int kScaleAnimationDurationMillis = 250; + +PageViewportControllerClientQt::PageViewportControllerClientQt(QQuickWebView* viewportItem, QQuickWebPage* pageItem) + : m_viewportItem(viewportItem) + , m_pageItem(pageItem) + , m_scaleAnimation(new ScaleAnimation(this)) + , m_pinchStartScale(-1) + , m_lastCommittedScale(-1) + , m_zoomOutScale(0) + , m_ignoreViewportChanges(true) +{ + m_scaleAnimation->setDuration(kScaleAnimationDurationMillis); + m_scaleAnimation->setEasingCurve(QEasingCurve::OutCubic); + + connect(m_viewportItem, SIGNAL(movementStarted()), SLOT(flickMoveStarted()), Qt::DirectConnection); + connect(m_viewportItem, SIGNAL(movementEnded()), SLOT(flickMoveEnded()), Qt::DirectConnection); + connect(m_viewportItem, SIGNAL(contentXChanged()), SLOT(pageItemPositionChanged())); + connect(m_viewportItem, SIGNAL(contentYChanged()), SLOT(pageItemPositionChanged())); + + + connect(m_scaleAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), + SLOT(scaleAnimationStateChanged(QAbstractAnimation::State, QAbstractAnimation::State))); +} + +void PageViewportControllerClientQt::ScaleAnimation::updateCurrentValue(const QVariant& value) +{ + // Resetting the end value, the easing curve or the duration of the scale animation + // triggers a recalculation of the animation interval. This might change the current + // value of the animated property. + // Make sure we only act on animation value changes if the animation is active. + if (!m_controllerClient->scaleAnimationActive()) + return; + + QRectF itemRect = value.toRectF(); + float itemScale = m_controllerClient->viewportScaleForRect(itemRect); + + m_controllerClient->setContentRectVisiblePositionAtScale(itemRect.topLeft(), itemScale); +} + +PageViewportControllerClientQt::~PageViewportControllerClientQt() +{ +} + +void PageViewportControllerClientQt::setContentRectVisiblePositionAtScale(const QPointF& location, qreal itemScale) +{ + ASSERT(itemScale >= 0); + + scaleContent(itemScale); + + // To animate the position together with the scale we multiply the position with the current scale + // and add it to the page position (displacement on the flickable contentItem because of additional items). + QPointF newPosition(m_pageItem->pos() + location * itemScale); + + m_viewportItem->setContentPos(newPosition); +} + +void PageViewportControllerClientQt::animateContentRectVisible(const QRectF& contentRect) +{ + ASSERT(m_scaleAnimation->state() == QAbstractAnimation::Stopped); + + ASSERT(!scrollAnimationActive()); + if (scrollAnimationActive()) + return; + + QRectF viewportRectInContentCoords = m_viewportItem->mapRectToWebContent(m_viewportItem->boundingRect()); + if (contentRect == viewportRectInContentCoords) { + updateViewportController(); + return; + } + + // Since we have to animate scale and position at the same time the scale animation interpolates + // from the current viewport rect in content coordinates to a visible rect of the content. + m_scaleAnimation->setStartValue(viewportRectInContentCoords); + m_scaleAnimation->setEndValue(contentRect); + + // Inform the web process about the requested visible content rect + // if zooming-out so that no white tiles are exposed during animation. + if (viewportRectInContentCoords.width() / contentRect.width() < m_pageItem->contentsScale()) + m_controller->setVisibleContentsRect(contentRect, viewportScaleForRect(contentRect)); + + m_scaleAnimation->start(); +} + +void PageViewportControllerClientQt::flickMoveStarted() +{ + Q_ASSERT(m_viewportItem->isMoving()); + m_scrollUpdateDeferrer.reset(new ViewportUpdateDeferrer(m_controller, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent)); + + m_lastScrollPosition = m_viewportItem->contentPos(); + + m_ignoreViewportChanges = false; +} + +void PageViewportControllerClientQt::flickMoveEnded() +{ + Q_ASSERT(!m_viewportItem->isMoving()); + // This method is called on the end of the pan or pan kinetic animation. + + m_ignoreViewportChanges = true; + + m_scrollUpdateDeferrer.reset(); +} + +void PageViewportControllerClientQt::pageItemPositionChanged() +{ + if (m_ignoreViewportChanges) + return; + + QPointF newPosition = m_viewportItem->contentPos(); + + updateViewportController(m_lastScrollPosition - newPosition); + + m_lastScrollPosition = newPosition; +} + +void PageViewportControllerClientQt::scaleAnimationStateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State /*oldState*/) +{ + switch (newState) { + case QAbstractAnimation::Running: + m_viewportItem->cancelFlick(); + ASSERT(!m_animationUpdateDeferrer); + m_animationUpdateDeferrer.reset(new ViewportUpdateDeferrer(m_controller, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent)); + break; + case QAbstractAnimation::Stopped: + m_animationUpdateDeferrer.reset(); + break; + default: + break; + } +} + +void PageViewportControllerClientQt::touchBegin() +{ + m_controller->setHadUserInteraction(true); + + // Prevents resuming the page between the user's flicks of the page while the animation is running. + if (scrollAnimationActive()) + m_touchUpdateDeferrer.reset(new ViewportUpdateDeferrer(m_controller, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent)); +} + +void PageViewportControllerClientQt::touchEnd() +{ + m_touchUpdateDeferrer.reset(); +} + +void PageViewportControllerClientQt::focusEditableArea(const QRectF& caretArea, const QRectF& targetArea) +{ + // This can only happen as a result of a user interaction. + ASSERT(m_controller->hadUserInteraction()); + + QRectF endArea = m_controller->convertToViewport(targetArea); + + qreal endItemScale = m_controller->convertToViewport(m_controller->innerBoundedContentsScale(2.0)); + const QRectF viewportRect = m_viewportItem->boundingRect(); + + qreal x; + const qreal borderOffset = 10; + if ((endArea.width() + borderOffset) * endItemScale <= viewportRect.width()) { + // Center the input field in the middle of the view, if it is smaller than + // the view at the scale target. + x = viewportRect.center().x() - endArea.width() * endItemScale / 2.0; + } else { + // Ensure that the caret always has borderOffset contents pixels to the right + // of it, and secondarily (if possible), that the area has borderOffset + // contents pixels to the left of it. + qreal caretOffset = m_controller->convertToViewport(caretArea.x()) - endArea.x(); + x = qMin(viewportRect.width() - (caretOffset + borderOffset) * endItemScale, borderOffset * endItemScale); + } + + const QPointF hotspot = QPointF(endArea.x(), endArea.center().y()); + const QPointF viewportHotspot = QPointF(x, /* FIXME: visibleCenter */ viewportRect.center().y()); + + QPointF endPosition = hotspot * endItemScale - viewportHotspot; + QRectF endPosRange = m_controller->positionRangeForContentAtScale(endItemScale); + + endPosition = boundPosition(endPosRange.topLeft(), endPosition, endPosRange.bottomRight()); + + QRectF endVisibleContentRect(endPosition / endItemScale, viewportRect.size() / endItemScale); + + animateContentRectVisible(endVisibleContentRect); +} + +void PageViewportControllerClientQt::zoomToAreaGestureEnded(const QPointF& touchPoint, const QRectF& targetArea) +{ + // This can only happen as a result of a user interaction. + ASSERT(m_controller->hadUserInteraction()); + + if (!targetArea.isValid()) + return; + + if (m_controller->hasSuspendedContent()) + return; + + const int margin = 10; // We want at least a little bit of margin. + QRectF endArea = m_controller->convertToViewport(targetArea.adjusted(-margin, -margin, margin, margin)); + + const QRectF viewportRect = m_viewportItem->boundingRect(); + + qreal targetCSSScale = viewportRect.size().width() / endArea.size().width(); + qreal endCSSScale = m_controller->innerBoundedContentsScale(qMin(targetCSSScale, qreal(2.5))); + qreal endItemScale = m_controller->convertToViewport(endCSSScale); + qreal currentScale = m_pageItem->contentsScale(); + + // We want to end up with the target area filling the whole width of the viewport (if possible), + // and centralized vertically where the user requested zoom. Thus our hotspot is the center of + // the targetArea x-wise and the requested zoom position, y-wise. + const QPointF hotspot = QPointF(endArea.center().x(), m_controller->convertToViewport(touchPoint.y())); + const QPointF viewportHotspot = viewportRect.center(); + + QPointF endPosition = hotspot * endCSSScale - viewportHotspot; + + QRectF endPosRange = m_controller->positionRangeForContentAtScale(endItemScale); + endPosition = boundPosition(endPosRange.topLeft(), endPosition, endPosRange.bottomRight()); + + QRectF endVisibleContentRect(endPosition / endItemScale, viewportRect.size() / endItemScale); + + enum { ZoomIn, ZoomBack, ZoomOut, NoZoom } zoomAction = ZoomIn; + + if (!m_scaleStack.isEmpty()) { + // Zoom back out if attempting to scale to the same current scale, or + // attempting to continue scaling out from the inner most level. + // Use fuzzy compare with a fixed error to be able to deal with largish differences due to pixel rounding. + if (fuzzyCompare(endItemScale, currentScale, 0.01)) { + // If moving the viewport would expose more of the targetRect and move at least 40 pixels, update position but do not scale out. + QRectF currentContentRect(visibleContentsRect()); + QRectF targetIntersection = endVisibleContentRect.intersected(targetArea); + if (!currentContentRect.contains(targetIntersection) + && (qAbs(endVisibleContentRect.top() - currentContentRect.top()) >= 40 + || qAbs(endVisibleContentRect.left() - currentContentRect.left()) >= 40)) + zoomAction = NoZoom; + else + zoomAction = ZoomBack; + } else if (fuzzyCompare(endItemScale, m_zoomOutScale, 0.01)) + zoomAction = ZoomBack; + else if (endItemScale < currentScale) + zoomAction = ZoomOut; + } + + switch (zoomAction) { + case ZoomIn: + m_scaleStack.append(ScaleStackItem(currentScale, m_viewportItem->contentPos().x())); + m_zoomOutScale = endItemScale; + break; + case ZoomBack: { + ScaleStackItem lastScale = m_scaleStack.takeLast(); + endItemScale = lastScale.scale; + endCSSScale = m_controller->convertFromViewport(lastScale.scale); + // Recalculate endPosition and bound it according to new scale. + endPosition.setY(hotspot.y() * endCSSScale - viewportHotspot.y()); + endPosition.setX(lastScale.xPosition); + endPosRange = m_controller->positionRangeForContentAtScale(endItemScale); + endPosition = boundPosition(endPosRange.topLeft(), endPosition, endPosRange.bottomRight()); + endVisibleContentRect = QRectF(endPosition / endItemScale, viewportRect.size() / endItemScale); + break; + } + case ZoomOut: + // Unstack all scale-levels deeper than the new level, so a zoom-back won't end up zooming in. + while (!m_scaleStack.isEmpty() && m_scaleStack.last().scale >= endItemScale) + m_scaleStack.removeLast(); + m_zoomOutScale = endItemScale; + break; + case NoZoom: + break; + } + + animateContentRectVisible(endVisibleContentRect); +} + +QRectF PageViewportControllerClientQt::nearestValidVisibleContentsRect() const +{ + float cssScale = m_controller->convertFromViewport(m_pageItem->contentsScale()); + float endItemScale = m_controller->convertToViewport(m_controller->innerBoundedContentsScale(cssScale)); + + const QRectF viewportRect = m_viewportItem->boundingRect(); + QPointF viewportHotspot = viewportRect.center(); + QPointF endPosition = m_viewportItem->mapToWebContent(viewportHotspot) * endItemScale - viewportHotspot; + + FloatRect endPosRange = m_controller->positionRangeForContentAtScale(endItemScale); + endPosition = boundPosition(endPosRange.minXMinYCorner(), endPosition, endPosRange.maxXMaxYCorner()); + + QRectF endVisibleContentRect(endPosition / endItemScale, viewportRect.size() / endItemScale); + + return endVisibleContentRect; +} + +void PageViewportControllerClientQt::setContentsPosition(const FloatPoint& localPoint) +{ + QPointF newPosition(m_pageItem->pos() + QPointF(localPoint)); + m_viewportItem->setContentPos(newPosition); + updateViewportController(); +} + +void PageViewportControllerClientQt::setContentsScale(float localScale, bool treatAsInitialValue) +{ + if (treatAsInitialValue) { + m_zoomOutScale = 0; + m_scaleStack.clear(); + setContentRectVisiblePositionAtScale(QPointF(), localScale); + } else + scaleContent(localScale); + + updateViewportController(); +} + +void PageViewportControllerClientQt::setContentsRectToNearestValidBounds() +{ + ViewportUpdateDeferrer guard(m_controller); + float validCSSScale = m_controller->innerBoundedContentsScale(m_controller->convertFromViewport(m_pageItem->contentsScale())); + setContentRectVisiblePositionAtScale(nearestValidVisibleContentsRect().topLeft(), m_controller->convertToViewport(validCSSScale)); +} + +void PageViewportControllerClientQt::didResumeContent() +{ + updateViewportController(); +} + +bool PageViewportControllerClientQt::scrollAnimationActive() const +{ + return m_viewportItem->isFlicking(); +} + +bool PageViewportControllerClientQt::panGestureActive() const +{ + return m_controller->hadUserInteraction() && m_viewportItem->isDragging(); +} + +void PageViewportControllerClientQt::panGestureStarted(const QPointF& position, qint64 eventTimestampMillis) +{ + // This can only happen as a result of a user interaction. + ASSERT(m_controller->hadUserInteraction()); + + m_viewportItem->handleFlickableMousePress(position, eventTimestampMillis); + m_lastPinchCenterInViewportCoordinates = position; +} + +void PageViewportControllerClientQt::panGestureRequestUpdate(const QPointF& position, qint64 eventTimestampMillis) +{ + m_viewportItem->handleFlickableMouseMove(position, eventTimestampMillis); + m_lastPinchCenterInViewportCoordinates = position; +} + +void PageViewportControllerClientQt::panGestureEnded(const QPointF& position, qint64 eventTimestampMillis) +{ + m_viewportItem->handleFlickableMouseRelease(position, eventTimestampMillis); + m_lastPinchCenterInViewportCoordinates = position; +} + +void PageViewportControllerClientQt::panGestureCancelled() +{ + // Reset the velocity samples of the flickable. + // This should only be called by the recognizer if we have a recognized + // pan gesture and receive a touch event with multiple touch points + // (ie. transition to a pinch gesture) as it does not move the content + // back inside valid bounds. + // When the pinch gesture ends, the content is positioned and scaled + // back to valid boundaries. + m_viewportItem->cancelFlick(); +} + +bool PageViewportControllerClientQt::scaleAnimationActive() const +{ + return m_scaleAnimation->state() == QAbstractAnimation::Running; +} + +void PageViewportControllerClientQt::cancelScrollAnimation() +{ + if (!scrollAnimationActive()) + return; + + // If the pan gesture recognizer receives a touch begin event + // during an ongoing kinetic scroll animation of a previous + // pan gesture, the animation is stopped and the content is + // immediately positioned back to valid boundaries. + + m_viewportItem->cancelFlick(); + setContentsRectToNearestValidBounds(); +} + +void PageViewportControllerClientQt::interruptScaleAnimation() +{ + // This interrupts the scale animation exactly where it is, even if it is out of bounds. + m_scaleAnimation->stop(); +} + +bool PageViewportControllerClientQt::pinchGestureActive() const +{ + return m_controller->hadUserInteraction() && (m_pinchStartScale > 0); +} + +void PageViewportControllerClientQt::pinchGestureStarted(const QPointF& pinchCenterInViewportCoordinates) +{ + // This can only happen as a result of a user interaction. + ASSERT(m_controller->hadUserInteraction()); + + if (!m_controller->allowsUserScaling()) + return; + + m_scaleStack.clear(); + m_zoomOutScale = 0.0; + + m_scaleUpdateDeferrer.reset(new ViewportUpdateDeferrer(m_controller, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent)); + + m_lastPinchCenterInViewportCoordinates = pinchCenterInViewportCoordinates; + m_pinchStartScale = m_pageItem->contentsScale(); +} + +void PageViewportControllerClientQt::pinchGestureRequestUpdate(const QPointF& pinchCenterInViewportCoordinates, qreal totalScaleFactor) +{ + ASSERT(m_controller->hasSuspendedContent()); + + if (!m_controller->allowsUserScaling()) + return; + + // Changes of the center position should move the page even if the zoom factor does not change. + const qreal cssScale = m_controller->convertFromViewport(m_pinchStartScale * totalScaleFactor); + + // Allow zooming out beyond mimimum scale on pages that do not explicitly disallow it. + const qreal targetItemScale = m_controller->convertToViewport(m_controller->outerBoundedContentsScale(cssScale)); + + scaleContent(targetItemScale, m_viewportItem->mapToWebContent(pinchCenterInViewportCoordinates)); + + const QPointF positionDiff = pinchCenterInViewportCoordinates - m_lastPinchCenterInViewportCoordinates; + m_lastPinchCenterInViewportCoordinates = pinchCenterInViewportCoordinates; + + m_viewportItem->setContentPos(m_viewportItem->contentPos() - positionDiff); + + // Inform the web process to render the currently visible area with low-resolution tiles not + // to expose white tiles during pinch gestures and to show fixed position layers correctly. + // The actual scale is restored after the pinch gesture ends. + updateViewportController(QPointF(), 1); +} + +void PageViewportControllerClientQt::pinchGestureEnded() +{ + ASSERT(m_controller->hasSuspendedContent()); + + if (!m_controller->allowsUserScaling()) + return; + + m_pinchStartScale = -1; + + animateContentRectVisible(nearestValidVisibleContentsRect()); + m_scaleUpdateDeferrer.reset(); // Clear after starting potential animation, which takes over deferring. +} + +void PageViewportControllerClientQt::pinchGestureCancelled() +{ + m_pinchStartScale = -1; + m_scaleUpdateDeferrer.reset(); +} + +QRectF PageViewportControllerClientQt::visibleContentsRect() const +{ + const QRectF visibleRect(m_viewportItem->boundingRect().intersected(m_pageItem->boundingRect())); + return m_viewportItem->mapRectToWebContent(visibleRect); +} + +void PageViewportControllerClientQt::didChangeContentsSize() +{ + // Emit for testing purposes, so that it can be verified that + // we didn't do scale adjustment. + emit m_viewportItem->experimental()->test()->contentsScaleCommitted(); + + if (!m_controller->hasSuspendedContent()) + setContentsRectToNearestValidBounds(); +} + +void PageViewportControllerClientQt::didChangeVisibleContents() +{ + qreal scale = m_pageItem->contentsScale(); + + if (scale != m_lastCommittedScale) + emit m_viewportItem->experimental()->test()->contentsScaleCommitted(); + m_lastCommittedScale = scale; + + // Ensure that updatePaintNode is always called before painting. + m_pageItem->update(); +} + +void PageViewportControllerClientQt::didChangeViewportAttributes() +{ + // Make sure we apply the new initial scale when deferring ends. + ViewportUpdateDeferrer guard(m_controller); + + emit m_viewportItem->experimental()->test()->devicePixelRatioChanged(); + emit m_viewportItem->experimental()->test()->viewportChanged(); +} + +void PageViewportControllerClientQt::updateViewportController(const QPointF& trajectory, qreal scale) +{ + FloatRect currentVisibleRect(visibleContentsRect()); + float viewportScale = (scale < 0) ? viewportScaleForRect(currentVisibleRect) : scale; + m_controller->setVisibleContentsRect(currentVisibleRect, viewportScale, trajectory); +} + +void PageViewportControllerClientQt::scaleContent(qreal itemScale, const QPointF& centerInCSSCoordinates) +{ + QPointF oldPinchCenterOnViewport = m_viewportItem->mapFromWebContent(centerInCSSCoordinates); + m_pageItem->setContentsScale(itemScale); + QPointF newPinchCenterOnViewport = m_viewportItem->mapFromWebContent(centerInCSSCoordinates); + m_viewportItem->setContentPos(m_viewportItem->contentPos() + (newPinchCenterOnViewport - oldPinchCenterOnViewport)); +} + +float PageViewportControllerClientQt::viewportScaleForRect(const QRectF& rect) const +{ + return static_cast<float>(m_viewportItem->width()) / static_cast<float>(rect.width()); +} + +} // namespace WebKit + +#include "moc_PageViewportControllerClientQt.cpp" diff --git a/Source/WebKit2/UIProcess/qt/QtViewportHandler.h b/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.h index 9237fe9f3..4d6aebc88 100644 --- a/Source/WebKit2/UIProcess/qt/QtViewportHandler.h +++ b/Source/WebKit2/UIProcess/qt/PageViewportControllerClientQt.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2011, 2012 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2011 Benjamin Poulain <benjamin@webkit.org> * * This library is free software; you can redistribute it and/or @@ -19,38 +19,45 @@ * */ -#ifndef QtViewportHandler_h -#define QtViewportHandler_h +#ifndef PageViewportControllerClientQt_h +#define PageViewportControllerClientQt_h -#include <QtCore/QObject> -#include <QtCore/QRectF> -#include <QtCore/QVariant> -#include <QtCore/QVariantAnimation> -#include <WebCore/ViewportArguments.h> -#include <wtf/OwnPtr.h> +#include "PageViewportController.h" +#include "PageViewportControllerClient.h" +#include <QObject> +#include <QPointF> +#include <QScopedPointer> +#include <QVariant> +#include <QVariantAnimation> QT_BEGIN_NAMESPACE -class QPointF; -class QWheelEvent; -QT_END_NAMESPACE - class QQuickWebPage; class QQuickWebView; +class QRectF; +QT_END_NAMESPACE class QWebKitTest; namespace WebKit { -class WebPageProxy; -class ViewportUpdateDeferrer; - -class QtViewportHandler : public QObject { +class PageViewportControllerClientQt : public QObject, public PageViewportControllerClient { Q_OBJECT public: - QtViewportHandler(WebPageProxy*, QQuickWebView*, QQuickWebPage*); - ~QtViewportHandler(); + PageViewportControllerClientQt(QQuickWebView*, QQuickWebPage*); + ~PageViewportControllerClientQt(); + + virtual void setContentsPosition(const FloatPoint& localPoint); + virtual void setContentsScale(float localScale, bool treatAsInitialValue); + virtual void didResumeContent(); + virtual void didChangeContentsSize(); + virtual void didChangeVisibleContents(); + virtual void didChangeViewportAttributes(); + + virtual void setController(PageViewportController* controller) { m_controller = controller; } + + // Additional methods currently only relevant in the QQuick context. void touchBegin(); void touchEnd(); @@ -75,83 +82,25 @@ public: void zoomToAreaGestureEnded(const QPointF& touchPoint, const QRectF& targetArea); void focusEditableArea(const QRectF& caretArea, const QRectF& targetArea); - void pageContentPositionRequested(const QPoint& position); - - void viewportItemSizeChanged(); - void viewportAttributesChanged(const WebCore::ViewportAttributes&); - void informVisibleContentChange(const QPointF& trajectory = QPointF()); - void pageContentsSizeChanged(const QSize& newSize, const QSize& viewportSize); - private Q_SLOTS: // Respond to changes of position that are not driven by us. void pageItemPositionChanged(); void scaleAnimationStateChanged(QAbstractAnimation::State, QAbstractAnimation::State); - void scaleAnimationValueChanged(QVariant value); void flickMoveStarted(); // Called when panning starts. void flickMoveEnded(); // Called when panning (+ kinetic animation) ends. private: - friend class ViewportUpdateDeferrer; - friend class ::QWebKitTest; - - WebPageProxy* const m_webPageProxy; - QQuickWebView* const m_viewportItem; - QQuickWebPage* const m_pageItem; - - qreal cssScaleFromItem(qreal) const; - qreal itemScaleFromCSS(qreal) const; - qreal itemCoordFromCSS(qreal) const; - QRectF itemRectFromCSS(const QRectF&) const; - - qreal innerBoundedCSSScale(qreal) const; - qreal outerBoundedCSSScale(qreal) const; - - void setInitialScaleIfNeeded(); - - void setCSSScale(qreal); - qreal currentCSSScale() const; - - void setPageItemRectVisible(const QRectF&); - void animatePageItemRectVisible(const QRectF&); - - QRectF visibleContentsRect() const; - QRectF initialRect() const; - QRectF nearestValidBounds() const; - - QRectF computePosRangeForPageItemAtScale(qreal itemScale) const; - void scaleContent(const QPointF& centerInCSSCoordinates, qreal cssScale); - - void suspendPageContent(); - void resumePageContent(); - - WebCore::ViewportAttributes m_rawAttributes; - - bool m_allowsUserScaling; - qreal m_minimumScale; - qreal m_maximumScale; - qreal m_devicePixelRatio; - - QSize m_layoutSize; - - int m_suspendCount; - bool m_hasSuspendedContent; - - OwnPtr<ViewportUpdateDeferrer> m_scaleUpdateDeferrer; - OwnPtr<ViewportUpdateDeferrer> m_scrollUpdateDeferrer; - OwnPtr<ViewportUpdateDeferrer> m_touchUpdateDeferrer; - OwnPtr<ViewportUpdateDeferrer> m_animationUpdateDeferrer; - - bool m_hadUserInteraction; - class ScaleAnimation : public QVariantAnimation { + PageViewportControllerClientQt* m_controllerClient; public: - ScaleAnimation(QObject* parent = 0) + ScaleAnimation(PageViewportControllerClientQt* parent) : QVariantAnimation(parent) + , m_controllerClient(parent) { } - virtual void updateCurrentValue(const QVariant&) { } + virtual void updateCurrentValue(const QVariant&); }; struct ScaleStackItem { @@ -164,6 +113,28 @@ private: qreal xPosition; }; + friend class ScaleAnimation; + friend class ::QWebKitTest; + + PageViewportController* m_controller; + QQuickWebView* const m_viewportItem; + QQuickWebPage* const m_pageItem; + + float viewportScaleForRect(const QRectF&) const; + QRectF visibleContentsRect() const; + QRectF nearestValidVisibleContentsRect() const; + + void setContentsRectToNearestValidBounds(); + void updateViewportController(const QPointF& trajectory = QPointF(), qreal scale = -1); + void setContentRectVisiblePositionAtScale(const QPointF& location, qreal itemScale); + void animateContentRectVisible(const QRectF& contentRect); + void scaleContent(qreal itemScale, const QPointF& centerInCSSCoordinates = QPointF()); + + QScopedPointer<ViewportUpdateDeferrer> m_scaleUpdateDeferrer; + QScopedPointer<ViewportUpdateDeferrer> m_scrollUpdateDeferrer; + QScopedPointer<ViewportUpdateDeferrer> m_touchUpdateDeferrer; + QScopedPointer<ViewportUpdateDeferrer> m_animationUpdateDeferrer; + ScaleAnimation* m_scaleAnimation; QPointF m_lastPinchCenterInViewportCoordinates; QPointF m_lastScrollPosition; @@ -171,8 +142,9 @@ private: qreal m_lastCommittedScale; qreal m_zoomOutScale; QList<ScaleStackItem> m_scaleStack; + bool m_ignoreViewportChanges; }; } // namespace WebKit -#endif // QtViewportHandler_h +#endif // PageViewportControllerClientQt_h diff --git a/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.cpp b/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.cpp index 93b6415c3..8c57c8898 100644 --- a/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.cpp +++ b/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.cpp @@ -41,9 +41,9 @@ void QtGestureRecognizer::reset() m_state = NoGesture; } -QtViewportHandler* QtGestureRecognizer::viewportHandler() +PageViewportControllerClientQt* QtGestureRecognizer::viewportController() { - return m_eventHandler->viewportHandler(); + return m_eventHandler->viewportController(); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.h b/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.h index 68e032f47..115e7179c 100644 --- a/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.h +++ b/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.h @@ -28,7 +28,7 @@ namespace WebKit { -class QtViewportHandler; +class PageViewportControllerClientQt; class QtWebPageEventHandler; class QtGestureRecognizer { @@ -46,7 +46,7 @@ protected: GestureRecognized } m_state; - QtViewportHandler* viewportHandler(); + PageViewportControllerClientQt* viewportController(); }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/QtPageClient.cpp b/Source/WebKit2/UIProcess/qt/QtPageClient.cpp index e2b390ab3..832b32d68 100644 --- a/Source/WebKit2/UIProcess/qt/QtPageClient.cpp +++ b/Source/WebKit2/UIProcess/qt/QtPageClient.cpp @@ -209,9 +209,9 @@ PassRefPtr<WebContextMenuProxy> QtPageClient::createContextMenuProxy(WebPageProx } #if ENABLE(INPUT_TYPE_COLOR) -PassRefPtr<WebColorChooserProxy> QtPageClient::createColorChooserProxy(WebPageProxy* webPageProxy, const WebCore::Color& initialColor) +PassRefPtr<WebColorChooserProxy> QtPageClient::createColorChooserProxy(WebPageProxy* webPageProxy, const WebCore::Color& initialColor, const WebCore::IntRect& elementRect) { - return WebColorChooserProxyQt::create(webPageProxy, m_webView, initialColor); + return WebColorChooserProxyQt::create(webPageProxy, m_webView, initialColor, elementRect); } #endif diff --git a/Source/WebKit2/UIProcess/qt/QtPageClient.h b/Source/WebKit2/UIProcess/qt/QtPageClient.h index 5c69ac879..a813894cc 100644 --- a/Source/WebKit2/UIProcess/qt/QtPageClient.h +++ b/Source/WebKit2/UIProcess/qt/QtPageClient.h @@ -21,6 +21,7 @@ #ifndef QtPageClient_h #define QtPageClient_h +#include "FindIndicator.h" #include "PageClient.h" class QQuickWebView; @@ -87,7 +88,7 @@ public: virtual PassRefPtr<WebPopupMenuProxy> createPopupMenuProxy(WebPageProxy*); virtual PassRefPtr<WebContextMenuProxy> createContextMenuProxy(WebPageProxy*); #if ENABLE(INPUT_TYPE_COLOR) - virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& intialColor); + virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& initialColor, const WebCore::IntRect&); #endif virtual void setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut, bool animate) { } virtual void didCommitLoadForMainFrame(bool useCustomRepresentation) { } diff --git a/Source/WebKit2/UIProcess/qt/QtPanGestureRecognizer.cpp b/Source/WebKit2/UIProcess/qt/QtPanGestureRecognizer.cpp index ba9c90a3f..0aaa06690 100644 --- a/Source/WebKit2/UIProcess/qt/QtPanGestureRecognizer.cpp +++ b/Source/WebKit2/UIProcess/qt/QtPanGestureRecognizer.cpp @@ -25,7 +25,7 @@ #include "config.h" #include "QtPanGestureRecognizer.h" -#include "QtViewportHandler.h" +#include "PageViewportControllerClientQt.h" #include "QtWebPageEventHandler.h" namespace WebKit { @@ -38,7 +38,7 @@ QtPanGestureRecognizer::QtPanGestureRecognizer(QtWebPageEventHandler* eventHandl bool QtPanGestureRecognizer::update(const QTouchEvent::TouchPoint& touchPoint, qint64 eventTimestampMillis) { - if (!viewportHandler()) + if (!viewportController()) return false; m_lastPosition = touchPoint.pos(); @@ -48,7 +48,7 @@ bool QtPanGestureRecognizer::update(const QTouchEvent::TouchPoint& touchPoint, q case NoGesture: m_state = GestureRecognitionStarted; m_firstScreenPosition = touchPoint.screenPos(); - viewportHandler()->cancelScrollAnimation(); + viewportController()->cancelScrollAnimation(); return false; case GestureRecognitionStarted: { // To start the gesture, the delta from start in screen coordinates @@ -58,11 +58,11 @@ bool QtPanGestureRecognizer::update(const QTouchEvent::TouchPoint& touchPoint, q return false; m_state = GestureRecognized; - viewportHandler()->panGestureStarted(touchPoint.pos(), eventTimestampMillis); + viewportController()->panGestureStarted(touchPoint.pos(), eventTimestampMillis); return true; } case GestureRecognized: - viewportHandler()->panGestureRequestUpdate(touchPoint.pos(), eventTimestampMillis); + viewportController()->panGestureRequestUpdate(touchPoint.pos(), eventTimestampMillis); return true; default: ASSERT_NOT_REACHED(); @@ -75,8 +75,8 @@ void QtPanGestureRecognizer::finish(const QTouchEvent::TouchPoint& touchPoint, q if (m_state == NoGesture) return; - ASSERT(viewportHandler()); - viewportHandler()->panGestureEnded(touchPoint.pos(), eventTimestampMillis); + ASSERT(viewportController()); + viewportController()->panGestureEnded(touchPoint.pos(), eventTimestampMillis); reset(); } @@ -85,8 +85,8 @@ void QtPanGestureRecognizer::cancel() if (m_state == NoGesture) return; - viewportHandler()->panGestureEnded(m_lastPosition, m_lastEventTimestampMillis); - viewportHandler()->panGestureCancelled(); + viewportController()->panGestureEnded(m_lastPosition, m_lastEventTimestampMillis); + viewportController()->panGestureCancelled(); reset(); } diff --git a/Source/WebKit2/UIProcess/qt/QtPinchGestureRecognizer.cpp b/Source/WebKit2/UIProcess/qt/QtPinchGestureRecognizer.cpp index 75d4d23b0..a10367a40 100644 --- a/Source/WebKit2/UIProcess/qt/QtPinchGestureRecognizer.cpp +++ b/Source/WebKit2/UIProcess/qt/QtPinchGestureRecognizer.cpp @@ -26,7 +26,8 @@ #include "config.h" #include "QtPinchGestureRecognizer.h" -#include "QtViewportHandler.h" + +#include "PageViewportControllerClientQt.h" #include "QtWebPageEventHandler.h" #include <QtCore/QLineF> @@ -47,7 +48,7 @@ QtPinchGestureRecognizer::QtPinchGestureRecognizer(QtWebPageEventHandler* eventH bool QtPinchGestureRecognizer::update(const QTouchEvent::TouchPoint& point1, const QTouchEvent::TouchPoint& point2) { - ASSERT(viewportHandler()); + ASSERT(viewportController()); const qreal currentFingerDistance = QLineF(point1.screenPos(), point2.screenPos()).length(); switch (m_state) { case NoGesture: @@ -59,7 +60,7 @@ bool QtPinchGestureRecognizer::update(const QTouchEvent::TouchPoint& point1, con if (pinchDistance < pinchInitialTriggerDistanceThreshold) return false; m_state = GestureRecognized; - viewportHandler()->pinchGestureStarted(computePinchCenter(point1, point2)); + viewportController()->pinchGestureStarted(computePinchCenter(point1, point2)); // We reset the initial span distance to the current distance of the // touch points in order to avoid the jump caused by the events which @@ -71,7 +72,7 @@ bool QtPinchGestureRecognizer::update(const QTouchEvent::TouchPoint& point1, con case GestureRecognized: const qreal totalScaleFactor = currentFingerDistance / m_initialFingerDistance; const QPointF touchCenterInViewCoordinates = computePinchCenter(point1, point2); - viewportHandler()->pinchGestureRequestUpdate(touchCenterInViewCoordinates, totalScaleFactor); + viewportController()->pinchGestureRequestUpdate(touchCenterInViewCoordinates, totalScaleFactor); return true; break; } @@ -85,8 +86,8 @@ void QtPinchGestureRecognizer::finish() if (m_state == NoGesture) return; - ASSERT(viewportHandler()); - viewportHandler()->pinchGestureEnded(); + ASSERT(viewportController()); + viewportController()->pinchGestureEnded(); reset(); } @@ -95,8 +96,8 @@ void QtPinchGestureRecognizer::cancel() if (m_state == NoGesture) return; - ASSERT(viewportHandler()); - viewportHandler()->pinchGestureCancelled(); + ASSERT(viewportController()); + viewportController()->pinchGestureCancelled(); reset(); } diff --git a/Source/WebKit2/UIProcess/qt/QtViewportHandler.cpp b/Source/WebKit2/UIProcess/qt/QtViewportHandler.cpp deleted file mode 100644 index faff331be..000000000 --- a/Source/WebKit2/UIProcess/qt/QtViewportHandler.cpp +++ /dev/null @@ -1,756 +0,0 @@ -/* - * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) - * Copyright (C) 2011 Benjamin Poulain <benjamin@webkit.org> - * - * 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 program 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 program; 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 "QtViewportHandler.h" - -#include "WebPageGroup.h" -#include "WebPageProxy.h" -#include "WebPreferences.h" -#include "qquickwebpage_p.h" -#include "qquickwebview_p.h" -#include "qwebkittest_p.h" -#include <QPointF> -#include <QTransform> -#include <QWheelEvent> -#include <QtQuick/qquickitem.h> -#include <wtf/PassOwnPtr.h> - -namespace WebKit { - -static const int kScaleAnimationDurationMillis = 250; - -// UPDATE DEFERRING (SUSPEND/RESUME) -// ================================= -// -// When interaction with the content, either by animating or by the hand of the user, -// it is important to ensure smooth animations of at least 60fps in order to give a -// good user experience. -// -// In order to do this we need to get rid of unknown factors. These include device -// sensors (geolocation, orientation updates etc), CSS3 animations, JavaScript -// exectution, sub resource loads etc. We do this by emitting suspend and resume -// signals, which are then handled by the viewport and propagates to the right place. -// -// For this reason the ViewportUpdateDeferrer guard must be used when we interact -// or animate the content. -// -// It should be noted that when we update content properties, we might receive notify -// signals send my the content item itself, and care should be taken to not act on -// these unconditionally. An example of this is the pinch zoom, which changes the -// position and will thus result in a QQuickWebPage::geometryChanged() signal getting -// emitted. -// -// If something should only be executed during update deferring, it is possible to -// check for that using ASSERT(m_suspendCount). - -class ViewportUpdateDeferrer { -public: - enum SuspendContentFlag { DeferUpdate, DeferUpdateAndSuspendContent }; - ViewportUpdateDeferrer(QtViewportHandler* handler, SuspendContentFlag suspendContentFlag = DeferUpdate) - : handler(handler) - { - handler->m_suspendCount++; - - // There is no need to suspend content for immediate updates - // only during animations or longer gestures. - if (suspendContentFlag == DeferUpdateAndSuspendContent) - handler->suspendPageContent(); - } - - ~ViewportUpdateDeferrer() - { - // We are calling setInitialScaleIfNeeded() here as it requires a - // possitive m_suspendCount due to the assert in setPageItemRectVisible(). - if (handler->m_suspendCount == 1) - handler->setInitialScaleIfNeeded(); - - if (--(handler->m_suspendCount)) - return; - - handler->resumePageContent(); - - // Make sure that tiles all around the viewport will be requested. - handler->informVisibleContentChange(QPointF()); - } - -private: - QtViewportHandler* const handler; -}; - -void QtViewportHandler::suspendPageContent() -{ - if (m_hasSuspendedContent) - return; - - m_hasSuspendedContent = true; - m_webPageProxy->suspendActiveDOMObjectsAndAnimations(); -} - -void QtViewportHandler::resumePageContent() -{ - if (!m_hasSuspendedContent) - return; - m_hasSuspendedContent = false; - m_webPageProxy->resumeActiveDOMObjectsAndAnimations(); -} - -// A floating point compare with absolute error. -static inline bool fuzzyCompare(qreal a, qreal b, qreal epsilon) -{ - return qAbs(a - b) < epsilon; -} - -inline qreal QtViewportHandler::cssScaleFromItem(qreal itemScale) const -{ - return itemScale / m_devicePixelRatio; -} - -inline qreal QtViewportHandler::itemScaleFromCSS(qreal cssScale) const -{ - return cssScale * m_devicePixelRatio; -} - -inline qreal QtViewportHandler::itemCoordFromCSS(qreal value) const -{ - return value * m_devicePixelRatio; -} - -static inline QPointF boundPosition(const QPointF minPosition, const QPointF& position, const QPointF& maxPosition) -{ - return QPointF(qBound(minPosition.x(), position.x(), maxPosition.x()), - qBound(minPosition.y(), position.y(), maxPosition.y())); -} - -inline QRectF QtViewportHandler::itemRectFromCSS(const QRectF& cssRect) const -{ - QRectF itemRect; - - itemRect.setX(itemCoordFromCSS(cssRect.x())); - itemRect.setY(itemCoordFromCSS(cssRect.y())); - itemRect.setWidth(itemCoordFromCSS(cssRect.width())); - itemRect.setHeight(itemCoordFromCSS(cssRect.height())); - - return itemRect; -} - -QtViewportHandler::QtViewportHandler(WebKit::WebPageProxy* proxy, QQuickWebView* viewportItem, QQuickWebPage* pageItem) - : m_webPageProxy(proxy) - , m_viewportItem(viewportItem) - , m_pageItem(pageItem) - , m_allowsUserScaling(false) - , m_minimumScale(1) - , m_maximumScale(1) - , m_devicePixelRatio(1) - , m_suspendCount(0) - , m_hasSuspendedContent(false) - , m_hadUserInteraction(false) - , m_scaleAnimation(new ScaleAnimation(this)) - , m_pinchStartScale(-1) - , m_lastCommittedScale(-1) - , m_zoomOutScale(0.0) -{ - m_scaleAnimation->setDuration(kScaleAnimationDurationMillis); - m_scaleAnimation->setEasingCurve(QEasingCurve::OutCubic); - - // Initializing Viewport Raw Attributes to avoid random negative scale factors - // if there is a race condition between the first layout and setting the viewport attributes for the first time. - m_rawAttributes.devicePixelRatio = m_devicePixelRatio; - m_rawAttributes.initialScale = 1; - m_rawAttributes.minimumScale = m_minimumScale; - m_rawAttributes.maximumScale = m_maximumScale; - m_rawAttributes.userScalable = m_allowsUserScaling; - - connect(m_viewportItem, SIGNAL(movementStarted()), SLOT(flickMoveStarted()), Qt::DirectConnection); - connect(m_viewportItem, SIGNAL(movementEnded()), SLOT(flickMoveEnded()), Qt::DirectConnection); - - connect(m_scaleAnimation, SIGNAL(valueChanged(QVariant)), - SLOT(scaleAnimationValueChanged(QVariant)), Qt::DirectConnection); - connect(m_scaleAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), - SLOT(scaleAnimationStateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), Qt::DirectConnection); -} - -QtViewportHandler::~QtViewportHandler() -{ -} - -qreal QtViewportHandler::innerBoundedCSSScale(qreal cssScale) const -{ - return qBound(m_minimumScale, cssScale, m_maximumScale); -} - -qreal QtViewportHandler::outerBoundedCSSScale(qreal cssScale) const -{ - if (m_allowsUserScaling) { - // Bounded by [0.1, 10.0] like the viewport meta code in WebCore. - qreal hardMin = qMax<qreal>(0.1, qreal(0.5) * m_minimumScale); - qreal hardMax = qMin<qreal>(10, qreal(2.0) * m_maximumScale); - return qBound(hardMin, cssScale, hardMax); - } - return innerBoundedCSSScale(cssScale); -} - -void QtViewportHandler::setInitialScaleIfNeeded() -{ - if (m_rawAttributes.layoutSize.isEmpty() || m_rawAttributes.initialScale < 0) - return; - - m_zoomOutScale = 0.0; - m_scaleStack.clear(); - - m_hadUserInteraction = false; - - // We must not animate here as the new contents size might be very different - // than the current one. - setPageItemRectVisible(initialRect()); - - m_rawAttributes.initialScale = -1; // Mark used. -} - -void QtViewportHandler::viewportAttributesChanged(const WebCore::ViewportAttributes& newAttributes) -{ - if (newAttributes.layoutSize.isEmpty()) - return; - - m_rawAttributes = newAttributes; - WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(m_rawAttributes); - - m_devicePixelRatio = m_rawAttributes.devicePixelRatio; // Should return value from the webPageProxy. - m_allowsUserScaling = !!m_rawAttributes.userScalable; - m_minimumScale = m_rawAttributes.minimumScale; - m_maximumScale = m_rawAttributes.maximumScale; - - // Make sure we apply the new initial scale when deferring ends. - ViewportUpdateDeferrer guard(this); - - emit m_viewportItem->experimental()->test()->viewportChanged(); -} - -void QtViewportHandler::pageContentsSizeChanged(const QSize& newSize, const QSize& viewportSize) -{ - if (viewportSize.isEmpty()) - return; - - float minimumScale = WebCore::computeMinimumScaleFactorForContentContained(m_rawAttributes, viewportSize, newSize); - - if (!qFuzzyCompare(minimumScale, m_rawAttributes.minimumScale)) { - m_minimumScale = minimumScale; - emit m_viewportItem->experimental()->test()->viewportChanged(); - - if (!m_hadUserInteraction && !m_hasSuspendedContent) { - // Emits contentsScaleChanged(); - setCSSScale(minimumScale); - } - } - - // Emit for testing purposes, so that it can be verified that - // we didn't do scale adjustment. - emit m_viewportItem->experimental()->test()->contentsScaleCommitted(); - - if (!m_hasSuspendedContent) { - ViewportUpdateDeferrer guard(this); - setPageItemRectVisible(nearestValidBounds()); - } -} - -void QtViewportHandler::setPageItemRectVisible(const QRectF& itemRect) -{ - ASSERT_WITH_MESSAGE(m_suspendCount, - "setPageItemRectVisible has to be guarded using a ViewportUpdateDeferrer."); - - if (itemRect.isEmpty()) - return; - - qreal itemScale = m_viewportItem->width() / itemRect.width(); - - m_pageItem->setContentsScale(itemScale); - - // To animate the position together with the scale we multiply the position with the current scale - // and add it to the page position (displacement on the flickable contentItem because of additional items). - QPointF newPosition(m_pageItem->pos() + (itemRect.topLeft() * itemScale)); - - m_viewportItem->setContentPos(newPosition); -} - -void QtViewportHandler::animatePageItemRectVisible(const QRectF& itemRect) -{ - ASSERT(m_scaleAnimation->state() == QAbstractAnimation::Stopped); - - ASSERT(!scrollAnimationActive()); - if (scrollAnimationActive()) - return; - - QRectF currentPageItemRectVisible = m_viewportItem->mapRectToWebContent(m_viewportItem->boundingRect()); - if (itemRect == currentPageItemRectVisible) - return; - - m_scaleAnimation->setStartValue(currentPageItemRectVisible); - m_scaleAnimation->setEndValue(itemRect); - - m_scaleAnimation->start(); -} - -void QtViewportHandler::flickMoveStarted() -{ - Q_ASSERT(m_viewportItem->isMoving()); - m_scrollUpdateDeferrer = adoptPtr(new ViewportUpdateDeferrer(this, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent)); - - m_lastScrollPosition = m_viewportItem->contentPos(); - connect(m_viewportItem, SIGNAL(contentXChanged()), SLOT(pageItemPositionChanged())); - connect(m_viewportItem, SIGNAL(contentYChanged()), SLOT(pageItemPositionChanged())); -} - -void QtViewportHandler::flickMoveEnded() -{ - Q_ASSERT(!m_viewportItem->isMoving()); - // This method is called on the end of the pan or pan kinetic animation. - m_scrollUpdateDeferrer.clear(); - - m_lastScrollPosition = QPointF(); - disconnect(m_viewportItem, SIGNAL(contentXChanged()), this, SLOT(pageItemPositionChanged())); - disconnect(m_viewportItem, SIGNAL(contentYChanged()), this, SLOT(pageItemPositionChanged())); -} - -void QtViewportHandler::pageItemPositionChanged() -{ - QPointF newPosition = m_viewportItem->contentPos(); - - informVisibleContentChange(m_lastScrollPosition - newPosition); - - m_lastScrollPosition = newPosition; -} - -void QtViewportHandler::pageContentPositionRequested(const QPoint& cssPosition) -{ - // Ignore the request if suspended. Can only happen due to delay in event delivery. - if (m_suspendCount) - return; - - qreal endItemScale = m_pageItem->contentsScale(); // Stay at same scale. - - QRectF endPosRange = computePosRangeForPageItemAtScale(endItemScale); - QPointF endPosition = boundPosition(endPosRange.topLeft(), cssPosition * endItemScale, endPosRange.bottomRight()); - - QRectF endVisibleContentRect(endPosition / endItemScale, m_viewportItem->boundingRect().size() / endItemScale); - - ViewportUpdateDeferrer guard(this); - setPageItemRectVisible(endVisibleContentRect); -} - -void QtViewportHandler::scaleAnimationStateChanged(QAbstractAnimation::State newState, QAbstractAnimation::State /*oldState*/) -{ - switch (newState) { - case QAbstractAnimation::Running: - m_viewportItem->cancelFlick(); - ASSERT(!m_animationUpdateDeferrer); - m_animationUpdateDeferrer = adoptPtr(new ViewportUpdateDeferrer(this, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent)); - break; - case QAbstractAnimation::Stopped: - m_animationUpdateDeferrer.clear(); - break; - default: - break; - } -} - -void QtViewportHandler::scaleAnimationValueChanged(QVariant value) -{ - // Resetting the end value, the easing curve or the duration of the scale animation - // triggers a recalculation of the animation interval. This might change the current - // value of the animated property. - // Make sure we only act on animation value changes if the animation is active. - if (!scaleAnimationActive()) - return; - - setPageItemRectVisible(value.toRectF()); -} - -void QtViewportHandler::touchBegin() -{ - m_hadUserInteraction = true; - - // Prevents resuming the page between the user's flicks of the page while the animation is running. - if (scrollAnimationActive()) - m_touchUpdateDeferrer = adoptPtr(new ViewportUpdateDeferrer(this, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent)); -} - -void QtViewportHandler::touchEnd() -{ - m_touchUpdateDeferrer.clear(); -} - -QRectF QtViewportHandler::computePosRangeForPageItemAtScale(qreal itemScale) const -{ - const QSizeF contentItemSize = m_pageItem->contentsSize() * itemScale; - const QSizeF viewportItemSize = m_viewportItem->boundingRect().size(); - - const qreal horizontalRange = contentItemSize.width() - viewportItemSize.width(); - const qreal verticalRange = contentItemSize.height() - viewportItemSize.height(); - - return QRectF(QPointF(0, 0), QSizeF(horizontalRange, verticalRange)); -} - -void QtViewportHandler::focusEditableArea(const QRectF& caretArea, const QRectF& targetArea) -{ - // This can only happen as a result of a user interaction. - ASSERT(m_hadUserInteraction); - - QRectF endArea = itemRectFromCSS(targetArea); - - qreal endItemScale = itemScaleFromCSS(innerBoundedCSSScale(2.0)); - const QRectF viewportRect = m_viewportItem->boundingRect(); - - qreal x; - const qreal borderOffset = 10; - if ((endArea.width() + borderOffset) * endItemScale <= viewportRect.width()) { - // Center the input field in the middle of the view, if it is smaller than - // the view at the scale target. - x = viewportRect.center().x() - endArea.width() * endItemScale / 2.0; - } else { - // Ensure that the caret always has borderOffset contents pixels to the right - // of it, and secondarily (if possible), that the area has borderOffset - // contents pixels to the left of it. - qreal caretOffset = itemCoordFromCSS(caretArea.x()) - endArea.x(); - x = qMin(viewportRect.width() - (caretOffset + borderOffset) * endItemScale, borderOffset * endItemScale); - } - - const QPointF hotspot = QPointF(endArea.x(), endArea.center().y()); - const QPointF viewportHotspot = QPointF(x, /* FIXME: visibleCenter */ viewportRect.center().y()); - - QPointF endPosition = hotspot * endItemScale - viewportHotspot; - QRectF endPosRange = computePosRangeForPageItemAtScale(endItemScale); - - endPosition = boundPosition(endPosRange.topLeft(), endPosition, endPosRange.bottomRight()); - - QRectF endVisibleContentRect(endPosition / endItemScale, viewportRect.size() / endItemScale); - - animatePageItemRectVisible(endVisibleContentRect); -} - -void QtViewportHandler::zoomToAreaGestureEnded(const QPointF& touchPoint, const QRectF& targetArea) -{ - // This can only happen as a result of a user interaction. - ASSERT(m_hadUserInteraction); - - if (!targetArea.isValid()) - return; - - if (m_suspendCount) - return; - - const int margin = 10; // We want at least a little bit of margin. - QRectF endArea = itemRectFromCSS(targetArea.adjusted(-margin, -margin, margin, margin)); - - const QRectF viewportRect = m_viewportItem->boundingRect(); - - qreal targetCSSScale = viewportRect.size().width() / endArea.size().width(); - qreal endCSSScale = innerBoundedCSSScale(qMin(targetCSSScale, qreal(2.5))); - qreal endItemScale = itemScaleFromCSS(endCSSScale); - qreal currentScale = m_pageItem->contentsScale(); - - // We want to end up with the target area filling the whole width of the viewport (if possible), - // and centralized vertically where the user requested zoom. Thus our hotspot is the center of - // the targetArea x-wise and the requested zoom position, y-wise. - const QPointF hotspot = QPointF(endArea.center().x(), itemCoordFromCSS(touchPoint.y())); - const QPointF viewportHotspot = viewportRect.center(); - - QPointF endPosition = hotspot * endCSSScale - viewportHotspot; - - QRectF endPosRange = computePosRangeForPageItemAtScale(endItemScale); - endPosition = boundPosition(endPosRange.topLeft(), endPosition, endPosRange.bottomRight()); - - QRectF endVisibleContentRect(endPosition / endItemScale, viewportRect.size() / endItemScale); - - enum { ZoomIn, ZoomBack, ZoomOut, NoZoom } zoomAction = ZoomIn; - - if (!m_scaleStack.isEmpty()) { - // Zoom back out if attempting to scale to the same current scale, or - // attempting to continue scaling out from the inner most level. - // Use fuzzy compare with a fixed error to be able to deal with largish differences due to pixel rounding. - if (fuzzyCompare(endItemScale, currentScale, 0.01)) { - // If moving the viewport would expose more of the targetRect and move at least 40 pixels, update position but do not scale out. - QRectF currentContentRect(m_viewportItem->contentPos() / currentScale, viewportRect.size() / currentScale); - QRectF targetIntersection = endVisibleContentRect.intersected(targetArea); - if (!currentContentRect.contains(targetIntersection) && (qAbs(endVisibleContentRect.top() - currentContentRect.top()) >= 40 || qAbs(endVisibleContentRect.left() - currentContentRect.left()) >= 40)) - zoomAction = NoZoom; - else - zoomAction = ZoomBack; - } else if (fuzzyCompare(endItemScale, m_zoomOutScale, 0.01)) - zoomAction = ZoomBack; - else if (endItemScale < currentScale) - zoomAction = ZoomOut; - } - - switch (zoomAction) { - case ZoomIn: - m_scaleStack.append(ScaleStackItem(currentScale, m_viewportItem->contentPos().x())); - m_zoomOutScale = endItemScale; - break; - case ZoomBack: { - ScaleStackItem lastScale = m_scaleStack.takeLast(); - endItemScale = lastScale.scale; - endCSSScale = cssScaleFromItem(lastScale.scale); - // Recalculate endPosition and bound it according to new scale. - endPosition.setY(hotspot.y() * endCSSScale - viewportHotspot.y()); - endPosition.setX(lastScale.xPosition); - endPosRange = computePosRangeForPageItemAtScale(endItemScale); - endPosition = boundPosition(endPosRange.topLeft(), endPosition, endPosRange.bottomRight()); - endVisibleContentRect = QRectF(endPosition / endItemScale, viewportRect.size() / endItemScale); - break; - } - case ZoomOut: - // Unstack all scale-levels deeper than the new level, so a zoom-back won't end up zooming in. - while (!m_scaleStack.isEmpty() && m_scaleStack.last().scale >= endItemScale) - m_scaleStack.removeLast(); - m_zoomOutScale = endItemScale; - break; - case NoZoom: - break; - } - - animatePageItemRectVisible(endVisibleContentRect); -} - -QRectF QtViewportHandler::initialRect() const -{ - ASSERT(m_rawAttributes.initialScale > 0); - - qreal endItemScale = itemScaleFromCSS(innerBoundedCSSScale(m_rawAttributes.initialScale)); - const QRectF viewportRect = m_viewportItem->boundingRect(); - QRectF endVisibleContentRect(QPointF(0, 0), viewportRect.size() / endItemScale); - - return endVisibleContentRect; -} - -QRectF QtViewportHandler::nearestValidBounds() const -{ - qreal endItemScale = itemScaleFromCSS(innerBoundedCSSScale(currentCSSScale())); - - const QRectF viewportRect = m_viewportItem->boundingRect(); - QPointF viewportHotspot = viewportRect.center(); - - QPointF endPosition = m_viewportItem->mapToWebContent(viewportHotspot) * endItemScale - viewportHotspot; - - QRectF endPosRange = computePosRangeForPageItemAtScale(endItemScale); - endPosition = boundPosition(endPosRange.topLeft(), endPosition, endPosRange.bottomRight()); - - QRectF endVisibleContentRect(endPosition / endItemScale, viewportRect.size() / endItemScale); - - return endVisibleContentRect; -} - -void QtViewportHandler::setCSSScale(qreal scale) -{ - ViewportUpdateDeferrer guard(this); - - qreal newScale = innerBoundedCSSScale(scale); - m_pageItem->setContentsScale(itemScaleFromCSS(newScale)); -} - -qreal QtViewportHandler::currentCSSScale() const -{ - return cssScaleFromItem(m_pageItem->contentsScale()); -} - -bool QtViewportHandler::scrollAnimationActive() const -{ - return m_viewportItem->isFlicking(); -} - -bool QtViewportHandler::panGestureActive() const -{ - return m_viewportItem->isDragging(); -} - -void QtViewportHandler::panGestureStarted(const QPointF& position, qint64 eventTimestampMillis) -{ - // This can only happen as a result of a user interaction. - ASSERT(m_hadUserInteraction); - - m_viewportItem->handleFlickableMousePress(position, eventTimestampMillis); - m_lastPinchCenterInViewportCoordinates = position; -} - -void QtViewportHandler::panGestureRequestUpdate(const QPointF& position, qint64 eventTimestampMillis) -{ - m_viewportItem->handleFlickableMouseMove(position, eventTimestampMillis); - m_lastPinchCenterInViewportCoordinates = position; -} - -void QtViewportHandler::panGestureEnded(const QPointF& position, qint64 eventTimestampMillis) -{ - m_viewportItem->handleFlickableMouseRelease(position, eventTimestampMillis); - m_lastPinchCenterInViewportCoordinates = position; -} - -void QtViewportHandler::panGestureCancelled() -{ - // Reset the velocity samples of the flickable. - // This should only be called by the recognizer if we have a recognized - // pan gesture and receive a touch event with multiple touch points - // (ie. transition to a pinch gesture) as it does not move the content - // back inside valid bounds. - // When the pinch gesture ends, the content is positioned and scaled - // back to valid boundaries. - m_viewportItem->cancelFlick(); -} - -bool QtViewportHandler::scaleAnimationActive() const -{ - return m_scaleAnimation->state() == QAbstractAnimation::Running; -} - -void QtViewportHandler::cancelScrollAnimation() -{ - if (!scrollAnimationActive()) - return; - - // If the pan gesture recognizer receives a touch begin event - // during an ongoing kinetic scroll animation of a previous - // pan gesture, the animation is stopped and the content is - // immediately positioned back to valid boundaries. - - m_viewportItem->cancelFlick(); - ViewportUpdateDeferrer guard(this); - setPageItemRectVisible(nearestValidBounds()); -} - -void QtViewportHandler::interruptScaleAnimation() -{ - // This interrupts the scale animation exactly where it is, even if it is out of bounds. - m_scaleAnimation->stop(); -} - -bool QtViewportHandler::pinchGestureActive() const -{ - return m_pinchStartScale > 0; -} - -void QtViewportHandler::pinchGestureStarted(const QPointF& pinchCenterInViewportCoordinates) -{ - // This can only happen as a result of a user interaction. - ASSERT(m_hadUserInteraction); - - if (!m_allowsUserScaling) - return; - - m_scaleStack.clear(); - m_zoomOutScale = 0.0; - - m_scaleUpdateDeferrer = adoptPtr(new ViewportUpdateDeferrer(this, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent)); - - m_lastPinchCenterInViewportCoordinates = pinchCenterInViewportCoordinates; - m_pinchStartScale = m_pageItem->contentsScale(); -} - -void QtViewportHandler::pinchGestureRequestUpdate(const QPointF& pinchCenterInViewportCoordinates, qreal totalScaleFactor) -{ - ASSERT(m_suspendCount); - - if (!m_allowsUserScaling) - return; - - // Changes of the center position should move the page even if the zoom factor - // does not change. - const qreal cssScale = cssScaleFromItem(m_pinchStartScale * totalScaleFactor); - - // Allow zooming out beyond mimimum scale on pages that do not explicitly disallow it. - const qreal targetCSSScale = outerBoundedCSSScale(cssScale); - - scaleContent(m_viewportItem->mapToWebContent(pinchCenterInViewportCoordinates), targetCSSScale); - - const QPointF positionDiff = pinchCenterInViewportCoordinates - m_lastPinchCenterInViewportCoordinates; - m_lastPinchCenterInViewportCoordinates = pinchCenterInViewportCoordinates; - - m_viewportItem->setContentPos(m_viewportItem->contentPos() - positionDiff); -} - -void QtViewportHandler::pinchGestureEnded() -{ - ASSERT(m_suspendCount); - - if (!m_allowsUserScaling) - return; - - m_pinchStartScale = -1; - - animatePageItemRectVisible(nearestValidBounds()); - m_scaleUpdateDeferrer.clear(); // Clear after starting potential animation, which takes over deferring. -} - -void QtViewportHandler::pinchGestureCancelled() -{ - m_pinchStartScale = -1; - m_scaleUpdateDeferrer.clear(); -} - -QRectF QtViewportHandler::visibleContentsRect() const -{ - const QRectF visibleRect(m_viewportItem->boundingRect().intersected(m_pageItem->boundingRect())); - return m_viewportItem->mapRectToWebContent(visibleRect); -} - -void QtViewportHandler::informVisibleContentChange(const QPointF& trajectoryVector) -{ - DrawingAreaProxy* drawingArea = m_webPageProxy->drawingArea(); - if (!drawingArea) - return; - - qreal scale = m_pageItem->contentsScale(); - - if (scale != m_lastCommittedScale) - emit m_viewportItem->experimental()->test()->contentsScaleCommitted(); - m_lastCommittedScale = scale; - - drawingArea->setVisibleContentsRect(visibleContentsRect(), scale, trajectoryVector); - - // Ensure that updatePaintNode is always called before painting. - m_pageItem->update(); -} - -void QtViewportHandler::viewportItemSizeChanged() -{ - QSize viewportSize = m_viewportItem->boundingRect().size().toSize(); - - if (viewportSize.isEmpty()) - return; - - // Let the WebProcess know about the new viewport size, so that - // it can resize the content accordingly. - m_webPageProxy->setViewportSize(viewportSize); - - informVisibleContentChange(QPointF()); -} - -void QtViewportHandler::scaleContent(const QPointF& centerInCSSCoordinates, qreal cssScale) -{ - QPointF oldPinchCenterOnViewport = m_viewportItem->mapFromWebContent(centerInCSSCoordinates); - m_pageItem->setContentsScale(itemScaleFromCSS(cssScale)); - QPointF newPinchCenterOnViewport = m_viewportItem->mapFromWebContent(centerInCSSCoordinates); - - m_viewportItem->setContentPos(m_viewportItem->contentPos() + (newPinchCenterOnViewport - oldPinchCenterOnViewport)); -} - -} // namespace WebKit - -#include "moc_QtViewportHandler.cpp" - - diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp index a02900fcd..64bcdbdf9 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp @@ -24,7 +24,7 @@ #include "NativeWebKeyboardEvent.h" #include "NativeWebMouseEvent.h" #include "NativeWebWheelEvent.h" -#include "QtViewportHandler.h" +#include "PageViewportControllerClientQt.h" #include "WebPageProxy.h" #include "qquickwebpage_p.h" #include "qquickwebview_p.h" @@ -91,7 +91,7 @@ static inline WebCore::DragOperation dropActionToDragOperation(Qt::DropActions a QtWebPageEventHandler::QtWebPageEventHandler(WKPageRef pageRef, QQuickWebPage* qmlWebPage, QQuickWebView* qmlWebView) : m_webPageProxy(toImpl(pageRef)) - , m_viewportHandler(0) + , m_viewportController(0) , m_panGestureRecognizer(this) , m_pinchGestureRecognizer(this) , m_tapGestureRecognizer(this) @@ -305,9 +305,9 @@ void QtWebPageEventHandler::handleFocusOutEvent(QFocusEvent*) m_webPageProxy->viewStateDidChange(WebPageProxy::ViewIsFocused | WebPageProxy::ViewWindowIsActive); } -void QtWebPageEventHandler::setViewportHandler(QtViewportHandler* handler) +void QtWebPageEventHandler::setViewportController(PageViewportControllerClientQt* controller) { - m_viewportHandler = handler; + m_viewportController = controller; } void QtWebPageEventHandler::handleInputMethodEvent(QInputMethodEvent* ev) @@ -398,7 +398,7 @@ void QtWebPageEventHandler::resetGestureRecognizers() static void setInputPanelVisible(bool visible) { - if (qApp->inputMethod()->visible() == visible) + if (qApp->inputMethod()->isVisible() == visible) return; qApp->inputMethod()->setVisible(visible); @@ -406,16 +406,16 @@ static void setInputPanelVisible(bool visible) void QtWebPageEventHandler::inputPanelVisibleChanged() { - if (!m_viewportHandler) + if (!m_viewportController) return; // We only respond to the input panel becoming visible. - if (!m_webView->hasActiveFocus() || !qApp->inputMethod()->visible()) + if (!m_webView->hasActiveFocus() || !qApp->inputMethod()->isVisible()) return; const EditorState& editor = m_webPageProxy->editorState(); if (editor.isContentEditable) - m_viewportHandler->focusEditableArea(QRectF(editor.cursorRect), QRectF(editor.editorRect)); + m_viewportController->focusEditableArea(QRectF(editor.cursorRect), QRectF(editor.editorRect)); } void QtWebPageEventHandler::updateTextInputState() @@ -450,7 +450,7 @@ void QtWebPageEventHandler::doneWithGestureEvent(const WebGestureEvent& event, b void QtWebPageEventHandler::handleInputEvent(const QInputEvent* event) { - ASSERT(m_viewportHandler); + ASSERT(m_viewportController); bool isMouseEvent = false; @@ -460,9 +460,9 @@ void QtWebPageEventHandler::handleInputEvent(const QInputEvent* event) m_isMouseButtonPressed = true; // Fall through. case QEvent::TouchBegin: - ASSERT(!m_viewportHandler->panGestureActive()); - ASSERT(!m_viewportHandler->pinchGestureActive()); - m_viewportHandler->touchBegin(); + ASSERT(!m_viewportController->panGestureActive()); + ASSERT(!m_viewportController->pinchGestureActive()); + m_viewportController->touchBegin(); // The interaction engine might still be animating kinetic scrolling or a scale animation // such as double-tap to zoom or the bounce back effect. A touch stops the kinetic scrolling @@ -477,15 +477,15 @@ void QtWebPageEventHandler::handleInputEvent(const QInputEvent* event) // Fall through. case QEvent::TouchUpdate: // The scale animation can only be interrupted by a pinch gesture, which will then take over. - if (m_viewportHandler->scaleAnimationActive() && m_pinchGestureRecognizer.isRecognized()) - m_viewportHandler->interruptScaleAnimation(); + if (m_viewportController->scaleAnimationActive() && m_pinchGestureRecognizer.isRecognized()) + m_viewportController->interruptScaleAnimation(); break; case QEvent::MouseButtonRelease: isMouseEvent = true; m_isMouseButtonPressed = false; // Fall through. case QEvent::TouchEnd: - m_viewportHandler->touchEnd(); + m_viewportController->touchEnd(); break; default: ASSERT(event->type() == QEvent::MouseButtonDblClick); @@ -494,7 +494,7 @@ void QtWebPageEventHandler::handleInputEvent(const QInputEvent* event) // If the scale animation is active we don't pass the event to the recognizers. In the future // we would want to queue the event here and repost then when the animation ends. - if (m_viewportHandler->scaleAnimationActive()) + if (m_viewportController->scaleAnimationActive()) return; QList<QTouchEvent::TouchPoint> activeTouchPoints; @@ -568,7 +568,7 @@ void QtWebPageEventHandler::handleInputEvent(const QInputEvent* event) #if ENABLE(TOUCH_EVENTS) void QtWebPageEventHandler::doneWithTouchEvent(const NativeWebTouchEvent& event, bool wasEventHandled) { - if (!m_viewportHandler) + if (!m_viewportController) return; if (wasEventHandled || event.type() == WebEvent::TouchCancel) { @@ -587,12 +587,12 @@ void QtWebPageEventHandler::doneWithTouchEvent(const NativeWebTouchEvent& event, void QtWebPageEventHandler::didFindZoomableArea(const IntPoint& target, const IntRect& area) { - if (!m_viewportHandler) + if (!m_viewportController) return; // FIXME: As the find method might not respond immediately during load etc, // we should ignore all but the latest request. - m_viewportHandler->zoomToAreaGestureEnded(QPointF(target), QRectF(area)); + m_viewportController->zoomToAreaGestureEnded(QPointF(target), QRectF(area)); } void QtWebPageEventHandler::startDrag(const WebCore::DragData& dragData, PassRefPtr<ShareableBitmap> dragImage) diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.h b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.h index 446db753d..8724f2ede 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.h +++ b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.h @@ -46,7 +46,7 @@ class IntRect; namespace WebKit { class NativeWebTouchEvent; -class QtViewportHandler; +class PageViewportControllerClientQt; class ShareableBitmap; class WebGestureEvent; class WebPageProxy; @@ -75,7 +75,7 @@ public: void handleInputMethodEvent(QInputMethodEvent*); void handleTouchEvent(QTouchEvent*); - void setViewportHandler(QtViewportHandler*); + void setViewportController(PageViewportControllerClientQt*); void activateTapHighlight(const QTouchEvent::TouchPoint&); void deactivateTapHighlight(); @@ -91,13 +91,13 @@ public: void handleInputEvent(const QInputEvent*); void resetGestureRecognizers(); - QtViewportHandler* viewportHandler() { return m_viewportHandler; } + PageViewportControllerClientQt* viewportController() { return m_viewportController; } void startDrag(const WebCore::DragData&, PassRefPtr<ShareableBitmap> dragImage); protected: WebPageProxy* m_webPageProxy; - QtViewportHandler* m_viewportHandler; + PageViewportControllerClientQt* m_viewportController; QtPanGestureRecognizer m_panGestureRecognizer; QtPinchGestureRecognizer m_pinchGestureRecognizer; QtTapGestureRecognizer m_tapGestureRecognizer; diff --git a/Source/WebKit2/UIProcess/qt/WebColorChooserProxyQt.cpp b/Source/WebKit2/UIProcess/qt/WebColorChooserProxyQt.cpp index 9fd296fd1..6b747b77b 100644 --- a/Source/WebKit2/UIProcess/qt/WebColorChooserProxyQt.cpp +++ b/Source/WebKit2/UIProcess/qt/WebColorChooserProxyQt.cpp @@ -34,16 +34,19 @@ namespace WebKit { class ColorChooserContextObject : public QObject { Q_OBJECT Q_PROPERTY(QColor currentColor READ currentColor CONSTANT FINAL) + Q_PROPERTY(QRectF elementRect READ elementRect CONSTANT FINAL) public: - ColorChooserContextObject(const QColor& color) + ColorChooserContextObject(const QColor& color, const QRectF& rect) : m_currentColor(color) + , m_rect(rect) { } QColor currentColor() const { return m_currentColor; } + QRectF elementRect() const { return m_rect; } - Q_INVOKABLE void accept(const QColor& color) { emit accepted(color); }; + Q_INVOKABLE void accept(const QColor& color) { emit accepted(color); } Q_INVOKABLE void reject() { emit rejected(); } Q_SIGNALS: @@ -52,13 +55,15 @@ Q_SIGNALS: private: QColor m_currentColor; + QRectF m_rect; }; -WebColorChooserProxyQt::WebColorChooserProxyQt(WebColorChooserProxy::Client* client, QQuickWebView* webView, const Color& initialColor) +WebColorChooserProxyQt::WebColorChooserProxyQt(WebColorChooserProxy::Client* client, QQuickWebView* webView, const Color& initialColor, const IntRect& elementRect) : WebColorChooserProxy(client) , m_webView(webView) { - ColorChooserContextObject* contextObject = new ColorChooserContextObject(initialColor); + const QRectF mappedRect= m_webView->mapRectFromWebContent(QRect(elementRect)); + ColorChooserContextObject* contextObject = new ColorChooserContextObject(initialColor, mappedRect); createItem(contextObject); } diff --git a/Source/WebKit2/UIProcess/qt/WebColorChooserProxyQt.h b/Source/WebKit2/UIProcess/qt/WebColorChooserProxyQt.h index 7872dc907..77c37fc84 100644 --- a/Source/WebKit2/UIProcess/qt/WebColorChooserProxyQt.h +++ b/Source/WebKit2/UIProcess/qt/WebColorChooserProxyQt.h @@ -21,6 +21,7 @@ #ifndef WebColorChooserProxyQt_h #define WebColorChooserProxyQt_h +#include "IntRect.h" #include "WebColorChooserProxy.h" #include <QtCore/QObject> #include <wtf/OwnPtr.h> @@ -43,9 +44,9 @@ class WebColorChooserProxyQt : public QObject, public WebColorChooserProxy { Q_OBJECT public: - static PassRefPtr<WebColorChooserProxy> create(WebColorChooserProxy::Client* client, QQuickWebView* webView, const WebCore::Color& initialColor) + static PassRefPtr<WebColorChooserProxy> create(WebColorChooserProxy::Client* client, QQuickWebView* webView, const WebCore::Color& initialColor, const WebCore::IntRect& elementRect) { - return adoptRef(new WebColorChooserProxyQt(client, webView, initialColor)); + return adoptRef(new WebColorChooserProxyQt(client, webView, initialColor, elementRect)); } ~WebColorChooserProxyQt(); @@ -58,7 +59,7 @@ private Q_SLOTS: void notifyColorSelected(const QColor&); private: - WebColorChooserProxyQt(WebColorChooserProxy::Client*, QQuickWebView*, const WebCore::Color&); + WebColorChooserProxyQt(WebColorChooserProxy::Client*, QQuickWebView*, const WebCore::Color&, const WebCore::IntRect&); void createItem(QObject*); void createContext(QQmlComponent*, QObject*); diff --git a/Source/WebKit2/UIProcess/qt/WebContextQt.cpp b/Source/WebKit2/UIProcess/qt/WebContextQt.cpp index 3f38dd288..f6af89d62 100644 --- a/Source/WebKit2/UIProcess/qt/WebContextQt.cpp +++ b/Source/WebKit2/UIProcess/qt/WebContextQt.cpp @@ -58,7 +58,12 @@ static String defaultDiskCacheDirectory() String WebContext::applicationCacheDirectory() { - return WebCore::cacheStorage().cacheDirectory(); + const String cacheDirectory = WebCore::cacheStorage().cacheDirectory(); + + if (cacheDirectory.isEmpty()) + return defaultDiskCacheDirectory(); + + return cacheDirectory; } void WebContext::platformInitializeWebProcess(WebProcessCreationParameters& parameters) diff --git a/Source/WebKit2/UIProcess/win/WebView.cpp b/Source/WebKit2/UIProcess/win/WebView.cpp index 28d26f1f3..70b875bb6 100644 --- a/Source/WebKit2/UIProcess/win/WebView.cpp +++ b/Source/WebKit2/UIProcess/win/WebView.cpp @@ -55,6 +55,7 @@ #include <WebCore/WebCoreInstanceHandle.h> #include <WebCore/WindowMessageBroadcaster.h> #include <WebCore/WindowsTouch.h> +#include <wtf/text/StringBuilder.h> #include <wtf/text/WTFString.h> #if USE(CG) @@ -1240,14 +1241,14 @@ static void compositionToUnderlines(const Vector<DWORD>& clauses, const Vector<B #define APPEND_ARGUMENT_NAME(name) \ if (lparam & name) { \ if (needsComma) \ - result += ", "; \ - result += #name; \ + result.appendLiteral(", "); \ + result.appendLiteral(#name); \ needsComma = true; \ } static String imeCompositionArgumentNames(LPARAM lparam) { - String result; + StringBuilder result; bool needsComma = false; APPEND_ARGUMENT_NAME(GCS_COMPATTR); @@ -1265,7 +1266,7 @@ static String imeCompositionArgumentNames(LPARAM lparam) APPEND_ARGUMENT_NAME(CS_INSERTCHAR); APPEND_ARGUMENT_NAME(CS_NOMOVECARET); - return result; + return result.toString(); } static String imeRequestName(WPARAM wparam) @@ -1430,7 +1431,7 @@ PassRefPtr<WebContextMenuProxy> WebView::createContextMenuProxy(WebPageProxy* pa } #if ENABLE(INPUT_TYPE_COLOR) -PassRefPtr<WebColorChooserProxy> WebView::createColorChooserProxy(WebPageProxy*, const WebCore::Color&) +PassRefPtr<WebColorChooserProxy> WebView::createColorChooserProxy(WebPageProxy*, const WebCore::Color&, const WebCore::IntRect&) { notImplemented(); return 0; diff --git a/Source/WebKit2/UIProcess/win/WebView.h b/Source/WebKit2/UIProcess/win/WebView.h index 71a9e578f..565633125 100644 --- a/Source/WebKit2/UIProcess/win/WebView.h +++ b/Source/WebKit2/UIProcess/win/WebView.h @@ -199,7 +199,7 @@ private: virtual PassRefPtr<WebPopupMenuProxy> createPopupMenuProxy(WebPageProxy*); virtual PassRefPtr<WebContextMenuProxy> createContextMenuProxy(WebPageProxy*); #if ENABLE(INPUT_TYPE_COLOR) - virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& intialColor); + virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& intialColor, const WebCore::IntRect&); #endif virtual void setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut, bool animate); virtual void didInstallOrUninstallPageOverlay(bool); |