diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
commit | ad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (patch) | |
tree | b34b0daceb7c8e7fdde4b4ec43650ab7caadb0a9 /Source/WebKit | |
parent | 03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (diff) | |
download | qtwebkit-ad0d549d4cc13433f77c1ac8f0ab379c83d93f28.tar.gz |
Imported WebKit commit bb52bf3c0119e8a128cd93afe5572413a8617de9 (http://svn.webkit.org/repository/webkit/trunk@108790)
Diffstat (limited to 'Source/WebKit')
318 files changed, 27671 insertions, 2680 deletions
diff --git a/Source/WebKit/CMakeLists.txt b/Source/WebKit/CMakeLists.txt index 3f3c80fb1..8bf565edc 100644 --- a/Source/WebKit/CMakeLists.txt +++ b/Source/WebKit/CMakeLists.txt @@ -22,6 +22,7 @@ SET(WebKit_INCLUDE_DIRECTORIES "${WEBCORE_DIR}/platform" "${WEBCORE_DIR}/platform/animation" "${WEBCORE_DIR}/platform/graphics" + "${WEBCORE_DIR}/platform/graphics/filters" "${WEBCORE_DIR}/platform/graphics/transforms" "${WEBCORE_DIR}/platform/network" "${WEBCORE_DIR}/platform/sql" @@ -44,6 +45,7 @@ SET(WebKit_INCLUDE_DIRECTORIES "${JAVASCRIPTCORE_DIR}/debugger" "${JAVASCRIPTCORE_DIR}/interpreter" "${JAVASCRIPTCORE_DIR}/jit" + "${JAVASCRIPTCORE_DIR}/llint" "${JAVASCRIPTCORE_DIR}/parser" "${JAVASCRIPTCORE_DIR}/profiler" "${JAVASCRIPTCORE_DIR}/runtime" @@ -65,7 +67,7 @@ SET(WebKit_LIBRARIES ${WebCore_LIBRARY_NAME} ) -INCLUDE_IF_EXISTS(${WEBKIT_DIR}/${WEBKIT_PORT_DIR}/CMakeLists${PORT}.txt) +WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS() ADD_DEFINITIONS(-DBUILDING_WebKit) INCLUDE_DIRECTORIES(${WebKit_INCLUDE_DIRECTORIES}) diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog index 678b840f5..c95efcf3c 100644 --- a/Source/WebKit/ChangeLog +++ b/Source/WebKit/ChangeLog @@ -1,3 +1,465 @@ +2012-02-23 Patrick Gansterer <paroga@webkit.org> + + [CMake] Add WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS macro + https://bugs.webkit.org/show_bug.cgi?id=79371 + + Reviewed by Daniel Bates. + + * CMakeLists.txt: + * PlatformBlackBerry.cmake: Renamed from Source/WebKit/blackberry/CMakeListsBlackBerry.txt. + * PlatformEfl.cmake: Renamed from Source/WebKit/efl/CMakeListsEfl.txt. + * PlatformWinCE.cmake: Renamed from Source/WebKit/wince/CMakeListsWinCE.txt. + +2012-02-20 Filip Pizlo <fpizlo@apple.com> + + JSC should be a triple-tier VM + https://bugs.webkit.org/show_bug.cgi?id=75812 + <rdar://problem/10079694> + + Reviewed by Gavin Barraclough. + + Changed EFL's build system to include a new directory in JavaScriptCore. + + * CMakeLists.txt: + +2012-02-21 Jon Lee <jonlee@apple.com> + + Bring notifications support to WK1 mac: showing, canceling, removing notifications + https://bugs.webkit.org/show_bug.cgi?id=78783 + <rdar://problem/10610578> + + Reviewed by Anders Carlsson. + + * WebKit.xcodeproj/project.pbxproj: Added new files. + +2012-02-21 Adam Roben <aroben@apple.com> + + Roll out r108309, r108323, and r108326 + + They broke the 32-bit Lion build. + + Original bugs is <http://webkit.org/b/75812> <rdar://problem/10079694>. + + * CMakeLists.txt: + +2012-02-16 Leo Yang <leo.yang@torchmobile.com.cn> + + [BlackBerry] Adapt to the removal of WebStringIml.h + https://bugs.webkit.org/show_bug.cgi?id=78784 + + Reviewed by Antonio Gomes. + + blackberry/WebCoreSupport/WebStringImpl.h which hasn't been upstreamed + has been removed internally. We should adapt to this removal for the + upstreamed part of the BlackBerry port. Actually WebStringImpl is not necessary + because it just inherits from WTF::StringImpl but adding nothing. + + * blackberry/Api/WebString.cpp: + (BlackBerry::WebKit::WebString::WebString): + (BlackBerry::WebKit::WebString::equalIgnoringCase): + * blackberry/Api/WebString.h: + (WTF): + +2012-02-16 Nima Ghanavatian <nghanavatian@rim.com> + + [BlackBerry] Style clean-up in WebPageCompositor + https://bugs.webkit.org/show_bug.cgi?id=78738 + + Reviewed by Rob Buis. + + No new functionality, no new tests. + + * blackberry/WebKitSupport/WebPageCompositor.cpp: + (BlackBerry::WebKit::WebPageCompositor::drawLayers): + * blackberry/WebKitSupport/WebPageCompositor.h: + (WebKit): + +2012-02-16 Patrick Gansterer <paroga@webkit.org> + + [CMake] Add missing include directories. + + * CMakeLists.txt: + +2012-02-15 Leo Yang <leo.yang@torchmobile.com.cn> + + [BlackBerry] Remove ResourceHolderImpl.cpp from build system + https://bugs.webkit.org/show_bug.cgi?id=78779 + + Reviewed by George Staikos. + + blackberry/Api/ResourceHolderImpl.cpp which hasn't been upstreamed + has been removed internally. So remove it from the build system. + + * blackberry/CMakeListsBlackBerry.txt: + +2012-02-15 Leo Yang <leo.yang@torchmobile.com.cn> + + [BlackBerry] Upstream WebPageGroupLoadDeferrer.{h, cpp} + https://bugs.webkit.org/show_bug.cgi?id=78770 + + Reviewed by Rob Buis. + + Initial upstreaming, no new tests. + + * blackberry/Api/WebPageGroupLoadDeferrer.cpp: Added. + * blackberry/Api/WebPageGroupLoadDeferrer.h: Added. + +2012-02-15 Konrad Piascik <kpiascik@rim.com> + + [BlackBerry] Upstream BlackBerry specific Web Inspector resources + https://bugs.webkit.org/show_bug.cgi?id=78727 + + Reviewed by Rob Buis. + + * blackberry/WebCoreSupport/inspectorBB.html: Added. + * blackberry/WebCoreSupport/inspectorBB.js: Added. + (): + (InspectorFrontendHost.copyText): + +2012-02-15 Mike Fenton <mifenton@rim.com> + + Initial upstreaming of EditorClientBlackBerry + https://bugs.webkit.org/show_bug.cgi?id=78730 + + Reviewed by Rob Buis. + + Initial upstreaming, no new tests. + + * blackberry/WebCoreSupport/EditorClientBlackBerry.cpp: Added. + (WebCore): + (WebCore::EditorClientBlackBerry::EditorClientBlackBerry): + (WebCore::EditorClientBlackBerry::pageDestroyed): + (WebCore::EditorClientBlackBerry::shouldDeleteRange): + (WebCore::EditorClientBlackBerry::shouldShowDeleteInterface): + (WebCore::EditorClientBlackBerry::smartInsertDeleteEnabled): + (WebCore::EditorClientBlackBerry::isSelectTrailingWhitespaceEnabled): + (WebCore::EditorClientBlackBerry::enableSpellChecking): + (WebCore::EditorClientBlackBerry::shouldSpellCheckFocusedField): + (WebCore::EditorClientBlackBerry::isContinuousSpellCheckingEnabled): + (WebCore::EditorClientBlackBerry::toggleContinuousSpellChecking): + (WebCore::EditorClientBlackBerry::isGrammarCheckingEnabled): + (WebCore::EditorClientBlackBerry::toggleGrammarChecking): + (WebCore::EditorClientBlackBerry::spellCheckerDocumentTag): + (WebCore::EditorClientBlackBerry::shouldBeginEditing): + (WebCore::EditorClientBlackBerry::shouldEndEditing): + (WebCore::EditorClientBlackBerry::shouldInsertNode): + (WebCore::EditorClientBlackBerry::shouldInsertText): + (WebCore::EditorClientBlackBerry::shouldChangeSelectedRange): + (WebCore::EditorClientBlackBerry::shouldApplyStyle): + (WebCore::EditorClientBlackBerry::shouldMoveRangeAfterDelete): + (WebCore::EditorClientBlackBerry::didBeginEditing): + (WebCore::EditorClientBlackBerry::respondToChangedContents): + (WebCore::EditorClientBlackBerry::respondToChangedSelection): + (WebCore::EditorClientBlackBerry::didEndEditing): + (WebCore::EditorClientBlackBerry::respondToSelectionAppearanceChange): + (WebCore::EditorClientBlackBerry::didWriteSelectionToPasteboard): + (WebCore::EditorClientBlackBerry::didSetSelectionTypesForPasteboard): + (WebCore::EditorClientBlackBerry::registerCommandForUndo): + (WebCore::EditorClientBlackBerry::registerCommandForRedo): + (WebCore::EditorClientBlackBerry::clearUndoRedoOperations): + (WebCore::EditorClientBlackBerry::canUndo): + (WebCore::EditorClientBlackBerry::canRedo): + (WebCore::EditorClientBlackBerry::canCopyCut): + (WebCore::EditorClientBlackBerry::canPaste): + (WebCore::EditorClientBlackBerry::undo): + (WebCore::EditorClientBlackBerry::redo): + (KeyDownEntry): + (KeyPressEntry): + (WebCore::EditorClientBlackBerry::interpretKeyEvent): + (WebCore::EditorClientBlackBerry::handleKeyboardEvent): + (WebCore::EditorClientBlackBerry::handleInputMethodKeydown): + (WebCore::EditorClientBlackBerry::textFieldDidBeginEditing): + (WebCore::EditorClientBlackBerry::textFieldDidEndEditing): + (WebCore::EditorClientBlackBerry::textDidChangeInTextField): + (WebCore::EditorClientBlackBerry::doTextFieldCommandFromEvent): + (WebCore::EditorClientBlackBerry::textWillBeDeletedInTextField): + (WebCore::EditorClientBlackBerry::textDidChangeInTextArea): + (WebCore::EditorClientBlackBerry::ignoreWordInSpellDocument): + (WebCore::EditorClientBlackBerry::learnWord): + (WebCore::EditorClientBlackBerry::checkSpellingOfString): + (WebCore::EditorClientBlackBerry::getAutoCorrectSuggestionForMisspelledWord): + (WebCore::EditorClientBlackBerry::checkGrammarOfString): + (WebCore::EditorClientBlackBerry::requestCheckingOfString): + (WebCore::EditorClientBlackBerry::textChecker): + (WebCore::EditorClientBlackBerry::updateSpellingUIWithGrammarString): + (WebCore::EditorClientBlackBerry::updateSpellingUIWithMisspelledWord): + (WebCore::EditorClientBlackBerry::showSpellingUI): + (WebCore::EditorClientBlackBerry::spellingUIIsShowing): + (WebCore::EditorClientBlackBerry::getGuessesForWord): + (WebCore::EditorClientBlackBerry::willSetInputMethodState): + (WebCore::EditorClientBlackBerry::setInputMethodState): + * blackberry/WebCoreSupport/EditorClientBlackBerry.h: Added. + (WebKit): + (WebCore): + (EditorClientBlackBerry): + +2012-02-15 Leo Yang <leo.yang@torchmobile.com.cn> + + [BlackBerry] Upstream WebPageClient.h + https://bugs.webkit.org/show_bug.cgi?id=78660 + + Reviewed by Antonio Gomes. + + Initial upstreaming, no new tests. + + * blackberry/Api/BackingStore.cpp: Add #include <BlackBerryPlatformWindow.h> because this inclusion + is being removed from WebPageClient.h. + * blackberry/Api/WebPageClient.h: Added. + * blackberry/WebCoreSupport/ChromeClientBlackBerry.cpp: Add #include <BlackBerryPlatformWindow.h> + because this inclusion is being removed from WebPageClient.h. + +2012-02-15 Rob Buis <rbuis@rim.com> + + [BlackBerry] Upstream remaining classes in Api + https://bugs.webkit.org/show_bug.cgi?id=78644 + + Reviewed by Antonio Gomes. + + No functionalities changed, no new tests. + + * blackberry/Api/ActiveNodeContext.h: Renamed from Source/WebKit/blackberry/Api/BlackBerryContext.h. + +2012-02-14 Nima Ghanavatian <nghanavatian@rim.com> + + [BlackBerry] Upstreaming WebSettings code + https://bugs.webkit.org/show_bug.cgi?id=78633 + + Reviewed by Rob Buis. + + Initial upstreaming, no new tests. + + * blackberry/Api/WebSettings.cpp: Added. + * blackberry/Api/WebSettings.h: Added. + * blackberry/Api/WebSettings_p.h: Added. + +2012-02-14 Nima Ghanavatian <nghanavatian@rim.com> + + [BlackBerry] Upstreaming DOMSupport files + https://bugs.webkit.org/show_bug.cgi?id=78607 + + Reviewed by Rob Buis. + + Initial upstreaming, no new tests. + + * blackberry/WebKitSupport/DOMSupport.cpp: Added. + * blackberry/WebKitSupport/DOMSupport.h: Added. + +2012-02-14 Jeff Rogers <jrogers@rim.com> + + [BlackBerry] Remove OpenVG references + https://bugs.webkit.org/show_bug.cgi?id=78623 + + Reviewed by Rob Buis. + + Removed references to USE(OPENVG) and the related code. + + * blackberry/Api/BackingStore.cpp: + (BlackBerry::WebKit::BackingStorePrivate::BackingStorePrivate): + (BlackBerry::WebKit::BackingStorePrivate::repaint): + (BlackBerry::WebKit::BackingStorePrivate::renderContents): + (BlackBerry::WebKit::BackingStore::createSurface): + * blackberry/Api/BackingStore_p.h: + +2012-02-14 Andy Chen <andchen@rim.com> + + Initial upstreaming for find-in-page for BlackBerry port + https://bugs.webkit.org/show_bug.cgi?id=78615 + + Create a new class InPageSearchManager for find-in-page and + remove the functions in SelectionHandler + + Reviewed by Rob Buis. + + * blackberry/CMakeListsBlackBerry.txt: + * blackberry/WebKitSupport/InPageSearchManager.cpp: Added. + (BlackBerry::WebKit::InPageSearchManager::InPageSearchManager): + (BlackBerry::WebKit::InPageSearchManager::~InPageSearchManager): + (BlackBerry::WebKit::InPageSearchManager::findNextString): + (BlackBerry::WebKit::InPageSearchManager::clearTextMatches): + (BlackBerry::WebKit::InPageSearchManager::setMarkerActive): + * blackberry/WebKitSupport/InPageSearchManager.h: Added. + * blackberry/WebKitSupport/SelectionHandler.cpp: + * blackberry/WebKitSupport/SelectionHandler.h: + +2012-02-14 Jacky Jiang <zhajiang@rim.com> + + [BlackBerry] Upstream BlackBerry WebCoreSupport FrameLoaderClientBlackBerry class + https://bugs.webkit.org/show_bug.cgi?id=78275 + + Reviewed by Rob Buis. + + Initial upstream, no new tests. + + * blackberry/WebCoreSupport/FrameLoaderClientBlackBerry.cpp: Added. + * blackberry/WebCoreSupport/FrameLoaderClientBlackBerry.h: Added. + +2012-02-14 Lianghui Chen <liachen@rim.com> + + Separate mimetype and file extension mapping API from WebKit/blackberry/Api/WebKitTextCodec and complete it. + https://bugs.webkit.org/show_bug.cgi?id=78605 + + Reviewed by Rob Buis. + + Now the MIME type and file extension mapping API are in WebKitMIMETypeConverter. + + * blackberry/Api/WebKitMIMETypeConverter.cpp: Added. + (WebKit): + (BlackBerry::WebKit::getExtensionForMimeType): + (BlackBerry::WebKit::getMimeTypeForExtension): + * blackberry/Api/WebKitMIMETypeConverter.h: Added. + (WebKit): + * blackberry/Api/WebKitTextCodec.cpp: + * blackberry/Api/WebKitTextCodec.h: + * blackberry/CMakeListsBlackBerry.txt: + +2012-02-14 Ed Baker <edbaker@rim.com> + + [BlackBerry] Dragging a selection handle outside of the content bounding box does not update the selection range correctly + https://bugs.webkit.org/show_bug.cgi?id=78608 + + Ensure that when selection handles leave the content bounding box that + the handle not being dragged remains fixed. Do not applying padding to + a direction that would cause the selection to shrink when performing + the handle direction detection. + + Reviewed by Rob Buis. + + * blackberry/WebKitSupport/SelectionHandler.cpp: + (BlackBerry::WebKit::directionOfPointRelativeToRect): + (BlackBerry::WebKit::SelectionHandler::extendSelectionToFieldBoundary): + (BlackBerry::WebKit::SelectionHandler::clipPointToFocusNode): + (BlackBerry::WebKit::SelectionHandler::setSelection): + * blackberry/WebKitSupport/SelectionHandler.h: + +2012-02-14 Rob Buis <rbuis@rim.com> + + [BlackBerry] Upstream remaining classes in Api + https://bugs.webkit.org/show_bug.cgi?id=78644 + + Reviewed by Antonio Gomes. + + Initial upstream, no new tests. + + * blackberry/Api/BlackBerryContext.h: Added. + * blackberry/Api/BlackBerryGlobal.cpp: Added. + * blackberry/Api/BlackBerryGlobal.h: Added. + * blackberry/Api/Version.cpp: Added. + * blackberry/Api/Version.h: Added. + +2012-02-14 Rob Buis <rbuis@rim.com> + + [BlackBerry] Upstream backing store related classes + https://bugs.webkit.org/show_bug.cgi?id=78517 + + Reviewed by Antonio Gomes. + + Initial upstream, no new tests. + + * blackberry/WebKitSupport/BackingStoreClient.cpp: Added. + * blackberry/WebKitSupport/BackingStoreClient.h: Added. + * blackberry/WebKitSupport/BackingStoreCompositingSurface.cpp: Added. + * blackberry/WebKitSupport/BackingStoreCompositingSurface.h: Added. + * blackberry/WebKitSupport/BackingStoreTile.cpp: Added. + * blackberry/WebKitSupport/BackingStoreTile.h: Added. + +2012-02-13 Nima Ghanavatian <nghanavatian@rim.com> + + Initial upstreaming of selection handling code for BlackBerry port + https://bugs.webkit.org/show_bug.cgi?id=78136 + + Reviewed by Rob Buis. + + Initial upstreaming, no new tests. + + * blackberry/WebKitSupport/SelectionHandler.cpp: Added. + * blackberry/WebKitSupport/SelectionHandler.h: Added. + +2012-02-10 Mike Fenton <mifenton@rim.com> + + BlackBerry Port - Input focus is suppressed during XHR loads + https://bugs.webkit.org/show_bug.cgi?id=78368 + + Allow JS to trigger the VKB and input focus when XHR scripting + is active. + + This switching the loaded state to checking the webpages loaded state + which is only updated after initial load. When additional loading + events happen for XHR, it remains false and focus events function. + + Also add detailed FocusLog's to shouldAcceptInputFocus. + + Reviewed by Rob Buis. + + * blackberry/WebKitSupport/InputHandler.cpp: + (BlackBerry::WebKit::InputHandler::shouldAcceptInputFocus): + +2012-02-10 Mike Fenton <mifenton@rim.com> + + BlackBerry Port - JS focus on blur can cause recursion + https://bugs.webkit.org/show_bug.cgi?id=78368 + + Prevent JS recursion of blur/focus by allowing focus + if we are already trying to prevent focus. + + Reviewed by Rob Buis. + + * blackberry/WebKitSupport/InputHandler.cpp: + (BlackBerry::WebKit::InputHandler::InputHandler): + (BlackBerry::WebKit::InputHandler::shouldAcceptInputFocus): + (BlackBerry::WebKit::InputHandler::setElementFocused): + * blackberry/WebKitSupport/InputHandler.h: + (InputHandler): + +2012-02-10 Rob Buis <rbuis@rim.com> + + [BlackBerry] Upstream graphics helper classes in WebKitSupport + https://bugs.webkit.org/show_bug.cgi?id=78278 + + Reviewed by Antonio Gomes. + + Initial upstream, no new tests. + + * blackberry/WebKitSupport/RenderQueue.cpp: Added. + * blackberry/WebKitSupport/RenderQueue.h: Added. + +2012-02-10 Rob Buis <rbuis@rim.com> + + [BlackBerry] Upstream graphics helper classes in WebKitSupport + https://bugs.webkit.org/show_bug.cgi?id=78278 + + Reviewed by Antonio Gomes. + + Initial upstream, no new tests. + + * blackberry/WebKitSupport/SurfacePool.cpp: Added. + * blackberry/WebKitSupport/SurfacePool.h: Added. + * blackberry/WebKitSupport/TileIndex.h: Added. + * blackberry/WebKitSupport/TileIndexHash.h: Added. + +2012-02-09 Leo Yang <leo.yang@torchmobile.com.cn> + + [BlackBerry] Upstream JavaScriptDebuggerBlackBerry.{h, cpp} + https://bugs.webkit.org/show_bug.cgi?id=78203 + + Reviewed by Rob Buis. + + Initial upstream, no new tests. + + * blackberry/WebCoreSupport/JavaScriptDebuggerBlackBerry.cpp: Added. + * blackberry/WebCoreSupport/JavaScriptDebuggerBlackBerry.h: Added. + +2012-02-09 Rob Buis <rbuis@rim.com> + + [BlackBerry] Upstream BlackBerry WebKitSupport WebPageCompositor class + https://bugs.webkit.org/show_bug.cgi?id=78276 + + Reviewed by Antonio Gomes. + + Initial upstream, no new tests. + + * blackberry/WebKitSupport/WebPageCompositor.cpp: Added. + * blackberry/WebKitSupport/WebPageCompositor.h: Added. + 2012-02-08 Jacky Jiang <zhajiang@rim.com> [BlackBerry] Upstream BlackBerry WebCoreSupport FrameNetworkingContextBlackBerry and IconDatabaseClientBlackBerry classes diff --git a/Source/WebKit/blackberry/CMakeListsBlackBerry.txt b/Source/WebKit/PlatformBlackBerry.cmake index d0e27cfd6..5d5c8b352 100644 --- a/Source/WebKit/blackberry/CMakeListsBlackBerry.txt +++ b/Source/WebKit/PlatformBlackBerry.cmake @@ -41,7 +41,7 @@ LIST(APPEND WebKit_SOURCES blackberry/Api/BackingStore.cpp blackberry/Api/BlackBerryGlobal.cpp blackberry/Api/WebString.cpp - blackberry/Api/ResourceHolderImpl.cpp + blackberry/Api/WebKitMIMETypeConverter.cpp blackberry/Api/WebKitTextCodec.cpp blackberry/Api/WebPage.cpp blackberry/Api/WebPageGroupLoadDeferrer.cpp @@ -67,6 +67,7 @@ LIST(APPEND WebKit_SOURCES blackberry/WebKitSupport/BackingStoreClient.cpp blackberry/WebKitSupport/DOMSupport.cpp blackberry/WebKitSupport/FrameLayers.cpp + blackberry/WebKitSupport/InPageSearchManager.cpp blackberry/WebKitSupport/InputHandler.cpp blackberry/WebKitSupport/OutOfMemoryHandler.cpp blackberry/WebKitSupport/RenderQueue.cpp diff --git a/Source/WebKit/efl/CMakeListsEfl.txt b/Source/WebKit/PlatformEfl.cmake index ec0c7d894..daf22876e 100644 --- a/Source/WebKit/efl/CMakeListsEfl.txt +++ b/Source/WebKit/PlatformEfl.cmake @@ -1,5 +1,3 @@ -INCLUDE(WebKitEfl) - LIST(APPEND WebKit_LINK_FLAGS ${ECORE_X_LDFLAGS} ${EDJE_LDFLAGS} @@ -10,6 +8,7 @@ LIST(APPEND WebKit_LINK_FLAGS LIST(APPEND WebKit_INCLUDE_DIRECTORIES "${WEBKIT_DIR}/efl/ewk" "${WEBKIT_DIR}/efl/WebCoreSupport" + "${JAVASCRIPTCORE_DIR}/wtf/gobject" "${WEBCORE_DIR}/platform/efl" "${WEBCORE_DIR}/platform/graphics/cairo" ${Cairo_INCLUDE_DIRS} @@ -20,6 +19,8 @@ LIST(APPEND WebKit_INCLUDE_DIRECTORIES ${LIBXML2_INCLUDE_DIR} ${LIBXSLT_INCLUDE_DIR} ${SQLITE_INCLUDE_DIR} + ${Glib_INCLUDE_DIRS} + ${LIBSOUP24_INCLUDE_DIRS} ) IF (ENABLE_SVG) @@ -71,15 +72,20 @@ LIST(APPEND WebKit_SOURCES efl/WebCoreSupport/DumpRenderTreeSupportEfl.cpp efl/WebCoreSupport/EditorClientEfl.cpp efl/WebCoreSupport/FrameLoaderClientEfl.cpp + efl/WebCoreSupport/FrameNetworkingContextEfl.cpp efl/WebCoreSupport/FullscreenVideoControllerEfl.cpp efl/WebCoreSupport/IconDatabaseClientEfl.cpp + efl/WebCoreSupport/StorageTrackerClientEfl.cpp efl/WebCoreSupport/InspectorClientEfl.cpp efl/WebCoreSupport/NotificationPresenterClientEfl.cpp + efl/ewk/ewk_auth.cpp + efl/ewk/ewk_auth_soup.cpp efl/ewk/ewk_contextmenu.cpp efl/ewk/ewk_cookies.cpp efl/ewk/ewk_frame.cpp efl/ewk/ewk_history.cpp + efl/ewk/ewk_js.cpp efl/ewk/ewk_main.cpp efl/ewk/ewk_network.cpp efl/ewk/ewk_security_policy.cpp @@ -92,7 +98,6 @@ LIST(APPEND WebKit_SOURCES efl/ewk/ewk_view_single.cpp efl/ewk/ewk_view_tiled.cpp efl/ewk/ewk_window_features.cpp - efl/ewk/ewk_js.cpp ) LIST(APPEND WebKit_LIBRARIES @@ -106,33 +111,19 @@ LIST(APPEND WebKit_LIBRARIES ${PNG_LIBRARY} ${JPEG_LIBRARY} ${CMAKE_DL_LIBS} -) - -IF (ENABLE_GLIB_SUPPORT) - LIST(APPEND WebKit_INCLUDE_DIRECTORIES - ${Gdk_INCLUDE_DIRS} - ${Glib_INCLUDE_DIRS} - ${JAVASCRIPTCORE_DIR}/wtf/gobject - ) - LIST(APPEND WebKit_LIBRARIES ${Glib_LIBRARIES} - ${Gdk_LIBRARIES} - ) -ENDIF () + ${LIBSOUP24_LIBRARIES} +) -IF (WTF_USE_SOUP) - LIST(APPEND WebKit_INCLUDE_DIRECTORIES ${LIBSOUP24_INCLUDE_DIRS}) - LIST(APPEND WebKit_LIBRARIES ${LIBSOUP24_LIBRARIES}) - LIST(APPEND WebKit_SOURCES - efl/ewk/ewk_auth.cpp - efl/ewk/ewk_auth_soup.cpp - ) +IF (ENABLE_VIBRATION) + LIST(APPEND WebKit_INCLUDE_DIRECTORIES + ${WEBCORE_DIR}/Modules/vibration + ) + LIST(APPEND WebKit_SOURCES + efl/WebCoreSupport/VibrationClientEfl.cpp + ) ENDIF () -IF (WTF_USE_CURL) - LIST(APPEND WebKit_INCLUDE_DIRECTORIES ${CURL_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS}) - LIST(APPEND WebKit_LIBRARIES ${CURL_LIBRARIES} ${ZLIB_LIBRARIES}) -ENDIF () SET(WebKit_THEME_DEFINITION "") IF (ENABLE_PROGRESS_TAG) @@ -235,6 +226,7 @@ UNSET(LIBS_PRIVATE) SET(EWebKit_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/efl/ewk/EWebKit.h ${CMAKE_CURRENT_SOURCE_DIR}/efl/ewk/ewk_auth.h + ${CMAKE_CURRENT_SOURCE_DIR}/efl/ewk/ewk_auth_soup.h ${CMAKE_CURRENT_SOURCE_DIR}/efl/ewk/ewk_contextmenu.h ${CMAKE_CURRENT_SOURCE_DIR}/efl/ewk/ewk_cookies.h ${CMAKE_CURRENT_SOURCE_DIR}/efl/ewk/ewk_frame.h @@ -249,10 +241,6 @@ SET(EWebKit_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/efl/ewk/ewk_window_features.h ) -IF (WTF_USE_SOUP) - LIST(APPEND EWebKit_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/efl/ewk/ewk_auth_soup.h) -ENDIF () - INSTALL(FILES ${EWebKit_HEADERS} DESTINATION include/${WebKit_LIBRARY_NAME}-${PROJECT_VERSION_MAJOR}) diff --git a/Source/WebKit/wince/CMakeListsWinCE.txt b/Source/WebKit/PlatformWinCE.cmake index de6de607e..de6de607e 100644 --- a/Source/WebKit/wince/CMakeListsWinCE.txt +++ b/Source/WebKit/PlatformWinCE.cmake diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj index 16cdf4c00..c8de755b6 100644 --- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj +++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj @@ -74,6 +74,9 @@ 226E9E6B09D0AA8200F3A2BC /* WebNetscapeDeprecatedFunctions.c in Sources */ = {isa = PBXBuildFile; fileRef = 226E9E6909D0AA8200F3A2BC /* WebNetscapeDeprecatedFunctions.c */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; }; 22F219CC08D236730030E078 /* WebBackForwardListPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 22F219CB08D236730030E078 /* WebBackForwardListPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 29AEF960134C76FB00FE5096 /* OutlookQuirksUserScript.js in Resources */ = {isa = PBXBuildFile; fileRef = 29AEF95D134C755400FE5096 /* OutlookQuirksUserScript.js */; }; + 312E2FE514E48182007CCA18 /* WebNotification.h in Headers */ = {isa = PBXBuildFile; fileRef = 312E2FE314E48182007CCA18 /* WebNotification.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 312E2FE614E48182007CCA18 /* WebNotification.mm in Sources */ = {isa = PBXBuildFile; fileRef = 312E2FE414E48182007CCA18 /* WebNotification.mm */; }; + 312E2FE914E48215007CCA18 /* WebNotificationInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 312E2FE814E48215007CCA18 /* WebNotificationInternal.h */; }; 31C11A6E1476552E0049A4CC /* WebNotificationClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 31C11A6C1476552E0049A4CC /* WebNotificationClient.h */; }; 31C11A6F1476552E0049A4CC /* WebNotificationClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = 31C11A6D1476552E0049A4CC /* WebNotificationClient.mm */; }; 37B6FB4E1063530C000FDB3B /* WebPDFDocumentExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 37B6FB4C1063530C000FDB3B /* WebPDFDocumentExtras.h */; }; @@ -456,6 +459,9 @@ 2D36FD5E03F78F9E00A80166 /* WebFormDelegatePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebFormDelegatePrivate.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 2D81DAB203EB0B2D00A80166 /* WebFormDelegate.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebFormDelegate.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 2D81DAB303EB0B2D00A80166 /* WebFormDelegate.m */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebFormDelegate.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; + 312E2FE314E48182007CCA18 /* WebNotification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebNotification.h; sourceTree = "<group>"; }; + 312E2FE414E48182007CCA18 /* WebNotification.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebNotification.mm; sourceTree = "<group>"; }; + 312E2FE814E48215007CCA18 /* WebNotificationInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebNotificationInternal.h; sourceTree = "<group>"; }; 31C11A6C1476552E0049A4CC /* WebNotificationClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebNotificationClient.h; sourceTree = "<group>"; }; 31C11A6D1476552E0049A4CC /* WebNotificationClient.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebNotificationClient.mm; sourceTree = "<group>"; }; 35081D9202B6D4D80ACA2ACA /* WebHTMLRepresentation.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; indentWidth = 4; path = WebHTMLRepresentation.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; @@ -1239,6 +1245,9 @@ F834AAD60E64B1C700E2737C /* WebTextIterator.mm */, 515E27CC0458C86500CA2D3A /* WebUIDelegate.h */, 65A7D44A0568AB2600E70EF6 /* WebUIDelegatePrivate.h */, + 312E2FE314E48182007CCA18 /* WebNotification.h */, + 312E2FE414E48182007CCA18 /* WebNotification.mm */, + 312E2FE814E48215007CCA18 /* WebNotificationInternal.h */, 51A8B579042834F700CA2D3A /* WebView.h */, 51A8B57A042834F700CA2D3A /* WebView.mm */, BC2E464B0FD8A96800A9D9DE /* WebViewData.h */, @@ -1632,6 +1641,8 @@ 9398109B0824BF01008DF038 /* WebViewInternal.h in Headers */, 939810710824BF01008DF038 /* WebViewPrivate.h in Headers */, 41F4484F10338E8C0030E55E /* WebWorkersPrivate.h in Headers */, + 312E2FE514E48182007CCA18 /* WebNotification.h in Headers */, + 312E2FE914E48215007CCA18 /* WebNotificationInternal.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2018,6 +2029,7 @@ 939811070824BF01008DF038 /* WebView.mm in Sources */, BC2E464E0FD8A96800A9D9DE /* WebViewData.mm in Sources */, 41F4485010338E8C0030E55E /* WebWorkersPrivate.mm in Sources */, + 312E2FE614E48182007CCA18 /* WebNotification.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/WebKit/blackberry/Api/ActiveNodeContext.h b/Source/WebKit/blackberry/Api/ActiveNodeContext.h new file mode 100644 index 000000000..1258d259f --- /dev/null +++ b/Source/WebKit/blackberry/Api/ActiveNodeContext.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ActiveNodeContext_h +#define ActiveNodeContext_h + +#include "WebString.h" + +namespace BlackBerry { +namespace WebKit { + +class ActiveNodeContext { +public: + // We assume a default context should be selectable, but nothing else. + ActiveNodeContext() + : m_flags(IsSelectable) + { + } + + enum ContextFlags { IsFocusable = 0x01, + IsInput = 0x02, + IsPassword = 0x04, + IsSelectable = 0x08, + IsSingleLine = 0x10, }; + + bool isFocusable() const { return m_flags & IsFocusable; } + bool isInput() const { return m_flags & IsInput; } + bool isPassword() const { return m_flags & IsPassword; } + bool isSelectable() const { return m_flags & IsSelectable; } + bool isSingleLine() const { return m_flags & IsSingleLine; } + + void setFlag(ContextFlags flag) { m_flags |= flag; } + void resetFlag(ContextFlags flag) { m_flags &= ~flag; } + + const WebString& imageAlt() const { return m_imageAlt; } + void setImageAlt(const WebString& string) { m_imageAlt = string; } + + const WebString& imageSrc() const { return m_imageSrc; } + void setImageSrc(const WebString& string) { m_imageSrc = string; } + + const WebString& pattern() const { return m_pattern; } + void setPattern(const WebString& string) { m_pattern = string; } + + const WebString& text() const { return m_text; } + void setText(const WebString& string) { m_text = string; } + + const WebString& url() const { return m_url; } + void setUrl(const WebString& string) { m_url = string; } + +private: + unsigned m_flags; + WebString m_imageAlt; + WebString m_imageSrc; + WebString m_pattern; + WebString m_text; + WebString m_url; +}; + +} +} +#endif // ActiveNodeContext_h diff --git a/Source/WebKit/blackberry/Api/BackingStore.cpp b/Source/WebKit/blackberry/Api/BackingStore.cpp index 036c9bbc0..2971d2698 100644 --- a/Source/WebKit/blackberry/Api/BackingStore.cpp +++ b/Source/WebKit/blackberry/Api/BackingStore.cpp @@ -39,6 +39,7 @@ #include <BlackBerryPlatformIntRectRegion.h> #include <BlackBerryPlatformMessage.h> #include <BlackBerryPlatformMessageClient.h> +#include <BlackBerryPlatformWindow.h> #include <wtf/CurrentTime.h> #include <wtf/MathExtras.h> @@ -54,11 +55,6 @@ #define DEBUG_TILEMATRIX 0 #define DEBUG_COMPOSITING_DIRTY_REGION 0 -#if USE(OPENVG) -#include "EGLDisplayOpenVG.h" -#include "EGLUtils.h" -#endif - #include <BlackBerryPlatformScreen.h> using namespace WebCore; @@ -202,9 +198,6 @@ BackingStorePrivate::BackingStorePrivate() , m_renderQueue(adoptPtr(new RenderQueue(this))) , m_defersBlit(true) , m_hasBlitJobs(false) -#if USE(OPENVG) - , m_eglDisplay(EGL_NO_DISPLAY) -#endif , m_currentWindowBackBuffer(0) , m_preferredTileMatrixDimension(Vertical) , m_blitGeneration(-1) @@ -298,10 +291,6 @@ void BackingStorePrivate::resumeScreenAndBackingStoreUpdates(BackingStore::Resum void BackingStorePrivate::repaint(const Platform::IntRect& windowRect, bool contentChanged, bool immediate) { -#if USE(OPENVG) - ASSERT(m_eglDisplay != EGL_NO_DISPLAY); -#endif - if (m_suspendBackingStoreUpdates) return; @@ -2215,9 +2204,6 @@ void BackingStorePrivate::renderContents(BlackBerry::Platform::Graphics::Buffer* } // Grab the requested region from the drawing surface into the tile image. -#if USE(OPENVG) - surface->makeCurrent(); -#endif delete bufferPlatformGraphicsContext; @@ -2525,23 +2511,9 @@ void BackingStore::createSurface() initialized = true; } -#if USE(OPENVG) - d->m_eglDisplay = BlackBerry::Platform::Graphics::eglDisplay(); - - // Make sure we are using OpenVG. - eglBindAPI(EGL_OPENVG_API); - ASSERT_EGL_NO_ERROR(); - - EGLDisplayOpenVG::setCurrentDisplay(d->m_eglDisplay); -#endif - // Triggers creation of surfaces in backingstore. d->createSurfaces(); -#if USE(OPENVG) - EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent(); -#endif - // Focusing the WebPage triggers a repaint, so while we want it to be // focused initially this has to happen after creation of the surface. d->m_webPage->setFocused(true); diff --git a/Source/WebKit/blackberry/Api/BackingStore_p.h b/Source/WebKit/blackberry/Api/BackingStore_p.h index 30abb592d..49c70a6a5 100644 --- a/Source/WebKit/blackberry/Api/BackingStore_p.h +++ b/Source/WebKit/blackberry/Api/BackingStore_p.h @@ -29,10 +29,6 @@ #include <wtf/HashMap.h> #include <wtf/Vector.h> -#if USE(OPENVG) -#include <egl.h> -#endif - #include <pthread.h> namespace WebCore { @@ -332,9 +328,6 @@ public: bool m_defersBlit; bool m_hasBlitJobs; -#if USE(OPENVG) - EGLDisplay m_eglDisplay; -#endif mutable unsigned m_frontState; mutable unsigned m_backState; diff --git a/Source/WebKit/blackberry/Api/BlackBerryGlobal.cpp b/Source/WebKit/blackberry/Api/BlackBerryGlobal.cpp new file mode 100644 index 000000000..6258a3cc3 --- /dev/null +++ b/Source/WebKit/blackberry/Api/BlackBerryGlobal.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "BlackBerryGlobal.h" + +#include "ApplicationCacheStorage.h" +#include "CacheClientBlackBerry.h" +#include "CookieManager.h" +#include "CrossOriginPreflightResultCache.h" +#include "FontCache.h" +#include "ImageSource.h" +#include "InitializeThreading.h" +#include "JSDOMWindow.h" +#include "JSGlobalData.h" +#include "Logging.h" +#include "MainThread.h" +#include "MemoryCache.h" +#include "NetworkStateNotifier.h" +#include "PageCache.h" +#include "PageGroup.h" +#include "TextureCacheCompositingThread.h" +#include "WebString.h" +#include "bindings/js/GCController.h" +#include "runtime/JSLock.h" +#include <BlackBerryPlatformExecutableMessage.h> +#include <BlackBerryPlatformMessageClient.h> +#include <BlackBerryPlatformSettings.h> + +using namespace WebCore; + +namespace BlackBerry { +namespace WebKit { + +static bool gIsGlobalInitialized = false; + +// Global initialization of various WebKit singletons. +void globalInitialize() +{ + if (gIsGlobalInitialized) + return; + gIsGlobalInitialized = true; + +#if ENABLE(BLACKBERRY_DEBUG_MEMORY) + blackberryDebugInitialize(); +#endif + + // Turn on logging. + initializeLoggingChannelsIfNecessary(); + + // Initialize threading/ + JSC::initializeThreading(); + + // Normally this is called from initializeThreading, but we're using ThreadingNone + // we're grabbing callOnMainThread without using the rest of the threading support. + WTF::initializeMainThread(); + + // Track visited links. + PageGroup::setShouldTrackVisitedLinks(true); + + CacheClientBlackBerry::get()->initialize(); + + BlackBerry::Platform::Settings* settings = BlackBerry::Platform::Settings::get(); + + ImageSource::setMaxPixelsPerDecodedImage(settings->maxPixelsPerDecodedImage()); +} + +void collectJavascriptGarbageNow() +{ + if (gIsGlobalInitialized) + gcController().garbageCollectNow(); +} + +void clearCookieCache() +{ + cookieManager().removeAllCookies(RemoveFromBackingStore); +} + +#if USE(ACCELERATED_COMPOSITING) +static void clearMemoryCachesInCompositingThread() +{ + textureCacheCompositingThread()->prune(0); +} +#endif + +void clearMemoryCaches() +{ +#if USE(ACCELERATED_COMPOSITING) + // Call textureCacheCompositingThread()->prune(0) in UI thread. + BlackBerry::Platform::userInterfaceThreadMessageClient()->dispatchMessage(BlackBerry::Platform::createFunctionCallMessage(clearMemoryCachesInCompositingThread)); +#endif + + { + JSC::JSLock lock(JSC::SilenceAssertionsOnly); + // This function also performs a GC. + JSC::releaseExecutableMemory(*JSDOMWindow::commonJSGlobalData()); + } + + // Clean caches after JS garbage collection because JS GC can + // generate more dead resources. + int capacity = pageCache()->capacity(); + pageCache()->setCapacity(0); + pageCache()->setCapacity(capacity); + pageCache()->releaseAutoreleasedPagesNow(); + + CrossOriginPreflightResultCache::shared().empty(); + + if (!memoryCache()->disabled()) { + // Evict all dead resources and prune live resources. + memoryCache()->setCapacities(0, 0, 0); + + // Update cache capacity based on current memory status. + CacheClientBlackBerry::get()->updateCacheCapacity(); + } + + fontCache()->invalidate(); +} + +void clearAppCache(const WebString& pageGroupName) +{ + cacheStorage().empty(); +} + +void clearLocalStorage(const WebString& pageGroupName) +{ +} + +void clearDatabase(const WebString& pageGroupName) +{ +} + +void updateOnlineStatus(bool online) +{ + networkStateNotifier().networkStateChange(online); +} + +} +} diff --git a/Source/WebKit/blackberry/Api/BlackBerryGlobal.h b/Source/WebKit/blackberry/Api/BlackBerryGlobal.h new file mode 100644 index 000000000..e794fb951 --- /dev/null +++ b/Source/WebKit/blackberry/Api/BlackBerryGlobal.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BlackBerryGlobal_h +#define BlackBerryGlobal_h + +#if defined(__QNXNTO__) && defined(BUILD_WEBKIT) + #define BLACKBERRY_EXPORT __attribute__ ((visibility("default"))) +#else + #define BLACKBERRY_EXPORT +#endif + +namespace BlackBerry { +namespace WebKit { + +class WebString; + +void globalInitialize(); +void collectJavascriptGarbageNow(); +void clearCookieCache(); +BLACKBERRY_EXPORT void clearMemoryCaches(); +void clearAppCache(const WebString& pageGroupName); +void reopenAllAppCaches(); +void closeAllAppCaches(); +void clearLocalStorage(const WebString& pageGroupName); +void closeAllLocalStorages(); +void clearDatabase(const WebString& pageGroupName); +void reopenAllTrackerDatabases(); +void closeAllTrackerDatabases(); +void updateOnlineStatus(bool online); +} +} + +#endif // BlackBerryGlobal_h diff --git a/Source/WebKit/blackberry/Api/Version.cpp b/Source/WebKit/blackberry/Api/Version.cpp new file mode 100644 index 000000000..23e7b7bd5 --- /dev/null +++ b/Source/WebKit/blackberry/Api/Version.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "Version.h" + +#include "WebKitVersion.h" // Note: auto generated at build time. + +// Make sure we are not treated as big endian nor middle endian. +#if PLATFORM(ARM) && (PLATFORM(BIG_ENDIAN) || PLATFORM(MIDDLE_ENDIAN)) +#error Our platform is little endian, but either PLATFORM(BIG_ENDIAN) or PLATFORM(MIDDLE_ENDIAN) is defined! +#endif + +namespace BlackBerry { +namespace WebKit { + +int webKitMajorVersion() +{ + return WEBKIT_MAJOR_VERSION; +} + +int webKitMinorVersion() +{ + return WEBKIT_MINOR_VERSION; +} + +} +} diff --git a/Source/WebKit/blackberry/Api/Version.h b/Source/WebKit/blackberry/Api/Version.h new file mode 100644 index 000000000..eedd7da8d --- /dev/null +++ b/Source/WebKit/blackberry/Api/Version.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef Version_h +#define Version_h + +namespace BlackBerry { +namespace WebKit { +int webKitMajorVersion(); +int webKitMinorVersion(); +} +} + +#endif // Version_h diff --git a/Source/WebKit/blackberry/Api/WebKitMIMETypeConverter.cpp b/Source/WebKit/blackberry/Api/WebKitMIMETypeConverter.cpp new file mode 100644 index 000000000..9c98af4e3 --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebKitMIMETypeConverter.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "WebKitMIMETypeConverter.h" + +#include "MIMETypeRegistry.h" +#include <wtf/text/CString.h> +#include <wtf/text/WTFString.h> + +namespace BlackBerry { +namespace WebKit { + +bool getExtensionForMimeType(const std::string& mime, std::string& extension) +{ + String mimeType(mime.data(), mime.length()); + String preferredExtension = WebCore::MIMETypeRegistry::getPreferredExtensionForMIMEType(mimeType); + if (preferredExtension.isEmpty()) + return false; + + CString utf8 = preferredExtension.utf8(); + extension.clear(); + extension.append(utf8.data(), utf8.length()); + return true; +} + +bool getMimeTypeForExtension(const std::string& extension, std::string& mimeType) +{ + String extStr(extension.data(), extension.length()); + String mime = WebCore::MIMETypeRegistry::getMediaMIMETypeForExtension(extStr); + if (mime.isEmpty()) + return false; + + CString utf8 = mime.utf8(); + mimeType.clear(); + mimeType.append(utf8.data(), utf8.length()); + return true; +} + +} // namespace WebKit +} // namespace BlackBerry diff --git a/Source/WebKit/blackberry/Api/WebKitMIMETypeConverter.h b/Source/WebKit/blackberry/Api/WebKitMIMETypeConverter.h new file mode 100644 index 000000000..3ff3d74f9 --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebKitMIMETypeConverter.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef WebKitMIMETypeConverter_h +#define WebKitMIMETypeConverter_h + +#include "BlackBerryGlobal.h" +#include <string> + +namespace BlackBerry { +namespace WebKit { + +BLACKBERRY_EXPORT bool getExtensionForMimeType(const std::string& mime, std::string& extension); +BLACKBERRY_EXPORT bool getMimeTypeForExtension(const std::string& extension, std::string& mimeType); + +} // namespace WebKit +} // namespace BlackBerry + +#endif // WebKitMIMETypeConverter_h diff --git a/Source/WebKit/blackberry/Api/WebKitTextCodec.cpp b/Source/WebKit/blackberry/Api/WebKitTextCodec.cpp index badb31fc7..3250601dd 100644 --- a/Source/WebKit/blackberry/Api/WebKitTextCodec.cpp +++ b/Source/WebKit/blackberry/Api/WebKitTextCodec.cpp @@ -21,7 +21,6 @@ #include "Base64.h" #include "KURL.h" -#include "MIMETypeRegistry.h" #include "TextCodecICU.h" #include <wtf/Vector.h> #include <wtf/text/CString.h> @@ -134,18 +133,5 @@ void escapeURL(const std::string& url, std::string& escaped) escaped.append(utf8.data(), utf8.length()); } -bool getExtensionForMimeType(const std::string& mime, std::string& extension) -{ - String mimeType(mime.data(), mime.length()); - String preferredExtension = WebCore::MIMETypeRegistry::getPreferredExtensionForMIMEType(mimeType); - if (preferredExtension.isEmpty()) - return false; - - CString utf8 = preferredExtension.utf8(); - extension.clear(); - extension.append(utf8.data(), utf8.length()); - return true; -} - } // namespace WebKit } // namespace BlackBerry diff --git a/Source/WebKit/blackberry/Api/WebKitTextCodec.h b/Source/WebKit/blackberry/Api/WebKitTextCodec.h index 318411a87..2834be793 100644 --- a/Source/WebKit/blackberry/Api/WebKitTextCodec.h +++ b/Source/WebKit/blackberry/Api/WebKitTextCodec.h @@ -55,8 +55,6 @@ BLACKBERRY_EXPORT bool base64Encode(const std::vector<char>& binary, std::string BLACKBERRY_EXPORT void unescapeURL(const std::string& escaped, std::string& url); BLACKBERRY_EXPORT void escapeURL(const std::string& url, std::string& escaped); -BLACKBERRY_EXPORT bool getExtensionForMimeType(const std::string& mime, std::string& extension); - } // namespace WebKit } // namespace BlackBerry diff --git a/Source/WebKit/blackberry/Api/WebPage.cpp b/Source/WebKit/blackberry/Api/WebPage.cpp new file mode 100644 index 000000000..f3ce5f0ce --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebPage.cpp @@ -0,0 +1,5598 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "WebPage.h" + +#include "ApplicationCacheStorage.h" +#include "BackForwardController.h" +#include "BackForwardListImpl.h" +#include "BackingStoreClient.h" +#include "BackingStoreCompositingSurface.h" +#include "BackingStore_p.h" +#include "CString.h" +#include "CachedImage.h" +#include "Chrome.h" +#include "ChromeClientBlackBerry.h" +#include "ContextMenuClientBlackBerry.h" +#include "CookieManager.h" +#include "DOMSupport.h" +#include "Database.h" +#include "DatabaseSync.h" +#include "DatabaseTracker.h" +#include "DeviceMotionClientBlackBerry.h" +#include "DeviceOrientationClientBlackBerry.h" +#include "DragClientBlackBerry.h" +// FIXME: We should be using DumpRenderTreeClient, but I'm not sure where we should +// create the DRT_BB object. See PR #120355. +#if ENABLE_DRT +#include "DumpRenderTreeBlackBerry.h" +#endif +#include "EditorClientBlackBerry.h" +#include "FocusController.h" +#include "FrameLoaderClientBlackBerry.h" +#if ENABLE(CLIENT_BASED_GEOLOCATION) +#if ENABLE_DRT +#include "GeolocationClientMock.h" +#endif +#include "GeolocationControllerClientBlackBerry.h" +#endif +#include "GroupSettings.h" +#include "HTMLAreaElement.h" +#include "HTMLFrameOwnerElement.h" +#include "HTMLImageElement.h" +#include "HTMLInputElement.h" +#include "HTMLNames.h" +#include "HTMLParserIdioms.h" +#include "HTTPParsers.h" +#include "HistoryItem.h" +#include "IconDatabaseClientBlackBerry.h" +#include "InPageSearchManager.h" +#include "InRegionScrollableArea.h" +#include "InputHandler.h" +#include "InspectorBackendDispatcher.h" +#include "InspectorClientBlackBerry.h" +#include "InspectorController.h" +#include "JavaScriptDebuggerBlackBerry.h" +#include "LayerWebKitThread.h" +#include "NetworkManager.h" +#include "NodeRenderStyle.h" +#include "Page.h" +#include "PageCache.h" +#include "PageGroup.h" +#include "PlatformTouchEvent.h" +#include "PlatformWheelEvent.h" +#include "PluginDatabase.h" +#include "PluginView.h" +#include "RenderText.h" +#include "RenderThemeBlackBerry.h" +#include "RenderTreeAsText.h" +#include "RenderView.h" +#include "RenderWidget.h" +#include "ScriptSourceCode.h" +#include "ScriptValue.h" +#include "ScrollTypes.h" +#include "SelectionHandler.h" +#include "Settings.h" +#include "Storage.h" +#include "StorageNamespace.h" +#include "SurfacePool.h" +#include "Text.h" +#include "ThreadCheck.h" +#include "TouchEventHandler.h" +#include "TransformationMatrix.h" +#include "VisiblePosition.h" +#if ENABLE(WEBDOM) +#include "WebDOMDocument.h" +#endif +#include "WebPageClient.h" +#include "WebSocket.h" +#include "npapi.h" +#include "runtime_root.h" + +#if ENABLE(VIDEO) +#include "HTMLMediaElement.h" +#include "MediaPlayer.h" +#include "MediaPlayerPrivateBlackBerry.h" +#endif + +#if USE(SKIA) +#include "PlatformContextSkia.h" +#endif + +#if USE(ACCELERATED_COMPOSITING) +#include "FrameLayers.h" +#include "WebPageCompositor.h" +#endif + +#include <BlackBerryPlatformExecutableMessage.h> +#include <BlackBerryPlatformITPolicy.h> +#include <BlackBerryPlatformKeyboardEvent.h> +#include <BlackBerryPlatformMessageClient.h> +#include <BlackBerryPlatformMouseEvent.h> +#include <BlackBerryPlatformScreen.h> +#include <BlackBerryPlatformSettings.h> +#include <JavaScriptCore/APICast.h> +#include <JavaScriptCore/JSContextRef.h> +#include <SharedPointer.h> +#include <sys/keycodes.h> +#include <unicode/ustring.h> // platform ICU + +#ifndef USER_PROCESSES +#include <memalloc.h> +#endif + +#if ENABLE(SKIA_GPU_CANVAS) +#include "BlackBerryPlatformGraphics.h" +#include "GrContext.h" +#endif + +#define DEBUG_BLOCK_ZOOM 0 +#define DEBUG_TOUCH_EVENTS 0 +#define DEBUG_WEBPAGE_LOAD 0 + +using namespace std; +using namespace WebCore; + +typedef const unsigned short* CUShortPtr; + +namespace BlackBerry { +namespace WebKit { + +static Vector<WebPage*>* visibleWebPages() +{ + static Vector<WebPage*>* s_visibleWebPages = 0; // Initially, no web page is visible. + if (!s_visibleWebPages) + s_visibleWebPages = new Vector<WebPage*>; + return s_visibleWebPages; +} + +const unsigned blockZoomMargin = 3; // Add 3 pixel margin on each side. +static int blockClickRadius = 0; +static double maximumBlockZoomScale = 3; // This scale can be clamped by the maximumScale set for the page. + +const double manualScrollInterval = 0.1; // The time interval during which we associate user action with scrolling. + +const double delayedZoomInterval = 0; + +const IntSize minimumLayoutSize(10, 10); // Needs to be a small size, greater than 0, that we can grow the layout from. +const IntSize maximumLayoutSize(10000, 10000); // Used with viewport meta tag, but we can still grow from this of course. + +const double minimumExpandingRatio = 0.15; + +// Helper function to parse a URL and fill in missing parts. +static KURL parseUrl(const String& url) +{ + String urlString(url); + KURL kurl = KURL(KURL(), urlString); + if (kurl.protocol().isEmpty()) { + urlString.insert("http://", 0); + kurl = KURL(KURL(), urlString); + } + + return kurl; +} + +// Helper functions to convert to and from WebCore types. +static inline MouseEventType toWebCoreMouseEventType(const Platform::MouseEvent::Type type) +{ + switch (type) { + case Platform::MouseEvent::MouseButtonDown: + return MouseEventPressed; + case Platform::MouseEvent::MouseButtonUp: + return MouseEventReleased; + case Platform::MouseEvent::MouseMove: + default: + return MouseEventMoved; + } +} + +static inline ResourceRequestCachePolicy toWebCoreCachePolicy(Platform::NetworkRequest::CachePolicy policy) +{ + switch (policy) { + case Platform::NetworkRequest::UseProtocolCachePolicy: + return UseProtocolCachePolicy; + case Platform::NetworkRequest::ReloadIgnoringCacheData: + return ReloadIgnoringCacheData; + case Platform::NetworkRequest::ReturnCacheDataElseLoad: + return ReturnCacheDataElseLoad; + case Platform::NetworkRequest::ReturnCacheDataDontLoad: + return ReturnCacheDataDontLoad; + default: + ASSERT_NOT_REACHED(); + return UseProtocolCachePolicy; + } +} + +#if ENABLE(EVENT_MODE_METATAGS) +static inline Platform::CursorEventMode toPlatformCursorEventMode(CursorEventMode mode) +{ + switch (mode) { + case ProcessedCursorEvents: + return Platform::ProcessedCursorEvents; + case NativeCursorEvents: + return Platform::NativeCursorEvents; + default: + ASSERT_NOT_REACHED(); + return Platform::ProcessedCursorEvents; + } +} + +static inline Platform::TouchEventMode toPlatformTouchEventMode(TouchEventMode mode) +{ + switch (mode) { + case ProcessedTouchEvents: + return Platform::ProcessedTouchEvents; + case NativeTouchEvents: + return Platform::NativeTouchEvents; + case PureTouchEventsWithMouseConversion: + return Platform::PureTouchEventsWithMouseConversion; + default: + ASSERT_NOT_REACHED(); + return Platform::ProcessedTouchEvents; + } +} +#endif + +static inline HistoryItem* historyItemFromBackForwardId(WebPage::BackForwardId id) +{ + return reinterpret_cast<HistoryItem*>(id); +} + +static inline WebPage::BackForwardId backForwardIdFromHistoryItem(HistoryItem* item) +{ + return reinterpret_cast<WebPage::BackForwardId>(item); +} + +WebPagePrivate::WebPagePrivate(WebPage* webPage, WebPageClient* client, const IntRect& rect) + : m_webPage(webPage) + , m_client(client) + , m_page(0) // Initialized by init. + , m_mainFrame(0) // Initialized by init. + , m_currentContextNode(0) + , m_webSettings(0) // Initialized by init. + , m_visible(false) + , m_shouldResetTilesWhenShown(false) + , m_userScalable(true) + , m_userPerformedManualZoom(false) + , m_userPerformedManualScroll(false) + , m_contentsSizeChanged(false) + , m_overflowExceedsContentsSize(false) + , m_resetVirtualViewportOnCommitted(true) + , m_shouldUseFixedDesktopMode(false) + , m_needTouchEvents(false) + , m_preventIdleDimmingCount(0) +#if ENABLE(TOUCH_EVENTS) + , m_preventDefaultOnTouchStart(false) +#endif + , m_nestedLayoutFinishedCount(0) + , m_actualVisibleWidth(rect.width()) + , m_actualVisibleHeight(rect.height()) + , m_virtualViewportWidth(0) + , m_virtualViewportHeight(0) + , m_defaultLayoutSize(minimumLayoutSize) + , m_didRestoreFromPageCache(false) + , m_viewMode(WebPagePrivate::Desktop) // Default to Desktop mode for PB. + , m_loadState(WebPagePrivate::None) + , m_transformationMatrix(new TransformationMatrix()) + , m_backingStore(0) // Initialized by init. + , m_backingStoreClient(0) // Initialized by init. + , m_inPageSearchManager(new InPageSearchManager(this)) + , m_inputHandler(new InputHandler(this)) + , m_selectionHandler(new SelectionHandler(this)) + , m_touchEventHandler(new TouchEventHandler(this)) +#if ENABLE(EVENT_MODE_METATAGS) + , m_cursorEventMode(ProcessedCursorEvents) + , m_touchEventMode(ProcessedTouchEvents) +#endif + , m_currentCursor(Platform::CursorNone) + , m_dumpRenderTree(0) // Lazy initialization. + , m_initialScale(-1.0) + , m_minimumScale(-1.0) + , m_maximumScale(-1.0) + , m_blockZoomFinalScale(1.0) + , m_anchorInNodeRectRatio(-1, -1) + , m_currentBlockZoomNode(0) + , m_currentBlockZoomAdjustedNode(0) + , m_shouldReflowBlock(false) + , m_delayedZoomTimer(adoptPtr(new Timer<WebPagePrivate>(this, &WebPagePrivate::zoomAboutPointTimerFired))) + , m_lastUserEventTimestamp(0.0) + , m_pluginMouseButtonPressed(false) + , m_pluginMayOpenNewTab(false) + , m_geolocationClient(0) + , m_inRegionScrollStartingNode(0) +#if USE(ACCELERATED_COMPOSITING) + , m_isAcceleratedCompositingActive(false) + , m_rootLayerCommitTimer(adoptPtr(new Timer<WebPagePrivate>(this, &WebPagePrivate::rootLayerCommitTimerFired))) + , m_needsOneShotDrawingSynchronization(false) + , m_needsCommit(false) + , m_suspendRootLayerCommit(false) +#endif + , m_pendingOrientation(-1) + , m_fullscreenVideoNode(0) + , m_hasInRegionScrollableAreas(false) + , m_updateDelegatedOverlaysDispatched(false) +{ +} + +WebPagePrivate::~WebPagePrivate() +{ + // Hand the backingstore back to another owner if necessary. + m_webPage->setVisible(false); + if (BackingStorePrivate::currentBackingStoreOwner() == m_webPage) + BackingStorePrivate::setCurrentBackingStoreOwner(0); + + delete m_webSettings; + m_webSettings = 0; + + delete m_backingStoreClient; + m_backingStoreClient = 0; + m_backingStore = 0; + + delete m_page; + m_page = 0; + + delete m_transformationMatrix; + m_transformationMatrix = 0; + + delete m_inPageSearchManager; + m_inPageSearchManager = 0; + + delete m_selectionHandler; + m_selectionHandler = 0; + + delete m_inputHandler; + m_inputHandler = 0; + + delete m_touchEventHandler; + m_touchEventHandler = 0; + +#if ENABLE_DRT + delete m_dumpRenderTree; + m_dumpRenderTree = 0; +#endif +} + +void WebPagePrivate::init(const WebString& pageGroupName) +{ + ChromeClientBlackBerry* chromeClient = new ChromeClientBlackBerry(this); + ContextMenuClientBlackBerry* contextMenuClient = 0; +#if ENABLE(CONTEXT_MENUS) + contextMenuClient = new ContextMenuClientBlackBerry(); +#endif + EditorClientBlackBerry* editorClient = new EditorClientBlackBerry(this); + DragClientBlackBerry* dragClient = 0; +#if ENABLE(DRAG_SUPPORT) + dragClient = new DragClientBlackBerry(); +#endif + InspectorClientBlackBerry* inspectorClient = 0; +#if ENABLE(INSPECTOR) + inspectorClient = new InspectorClientBlackBerry(this); +#endif + + FrameLoaderClientBlackBerry* frameLoaderClient = new FrameLoaderClientBlackBerry(); + + Page::PageClients pageClients; + pageClients.chromeClient = chromeClient; + pageClients.contextMenuClient = contextMenuClient; + pageClients.editorClient = editorClient; + pageClients.dragClient = dragClient; + pageClients.inspectorClient = inspectorClient; + +#if ENABLE(CLIENT_BASED_GEOLOCATION) + // Note the object will be destroyed when the page is destroyed. +#if ENABLE_DRT + if (getenv("drtRun")) + pageClients.geolocationClient = new GeolocationClientMock(); + else +#endif + pageClients.geolocationClient = m_geolocationClient = new GeolocationControllerClientBlackBerry(this); +#else + pageClients.geolocationClient = m_geolocationClient; +#endif + + pageClients.deviceMotionClient = new DeviceMotionClientBlackBerry(this); + pageClients.deviceOrientationClient = new DeviceOrientationClientBlackBerry(this); + m_page = new Page(pageClients); + +#if ENABLE(CLIENT_BASED_GEOLOCATION) && ENABLE_DRT + // In case running in DumpRenderTree mode set the controller to mock provider. + if (getenv("drtRun")) + static_cast<GeolocationClientMock*>(pageClients.geolocationClient)->setController(m_page->geolocationController()); +#endif + + m_page->setCustomHTMLTokenizerChunkSize(256); + m_page->setCustomHTMLTokenizerTimeDelay(0.3); + + m_webSettings = WebSettings::createFromStandardSettings(); + + // FIXME: We explicitly call setDelegate() instead of passing ourself in createFromStandardSettings() + // so that we only get one didChangeSettings() callback when we set the page group name. This causes us + // to make a copy of the WebSettings since some WebSettings method make use of the page group name. + // Instead, we shouldn't be storing the page group name in WebSettings. + m_webSettings->setDelegate(this); + m_webSettings->setPageGroupName(pageGroupName); + + RefPtr<Frame> newFrame = Frame::create(m_page, /* HTMLFrameOwnerElement* */ 0, frameLoaderClient); + + m_mainFrame = newFrame.get(); + frameLoaderClient->setFrame(m_mainFrame, this); + m_mainFrame->init(); + +#if ENABLE(WEBGL) + Platform::Settings* settings = Platform::Settings::get(); + m_page->settings()->setWebGLEnabled(settings && settings->isWebGLSupported()); +#endif +#if ENABLE(SKIA_GPU_CANVAS) + m_page->settings()->setCanvasUsesAcceleratedDrawing(true); + m_page->settings()->setAccelerated2dCanvasEnabled(true); +#endif +#if ENABLE(VIEWPORT_REFLOW) + m_page->settings()->setTextReflowEnabled(m_webSettings->textReflowMode() == WebSettings::TextReflowEnabled); +#endif + + m_page->settings()->setUseHixie76WebSocketProtocol(false); + m_page->settings()->setInteractiveFormValidationEnabled(true); + m_page->settings()->setAllowUniversalAccessFromFileURLs(false); + + m_backingStoreClient = BackingStoreClient::create(m_mainFrame, /* parent frame */ 0, m_webPage); + // The direct access to BackingStore is left here for convenience since it + // is owned by BackingStoreClient and then deleted by its destructor. + m_backingStore = m_backingStoreClient->backingStore(); + + m_page->settings()->setSpatialNavigationEnabled(m_webSettings->isSpatialNavigationEnabled()); + blockClickRadius = int(roundf(0.35 * Platform::Graphics::Screen::pixelsPerInch(0).width())); // The clicked rectangle area should be a fixed unit of measurement. + + m_page->settings()->setDelegateSelectionPaint(true); +} + +void WebPagePrivate::load(const char* url, const char* networkToken, const char* method, Platform::NetworkRequest::CachePolicy cachePolicy, const char* data, size_t dataLength, const char* const* headers, size_t headersLength, bool isInitial, bool mustHandleInternally, bool forceDownload, const char* overrideContentType) +{ + stopCurrentLoad(); + + String urlString(url); + if (urlString.startsWith("vs:", false)) { + urlString = urlString.substring(3); + m_mainFrame->setInViewSourceMode(true); + } else + m_mainFrame->setInViewSourceMode(false); + + KURL kurl = parseUrl(urlString); + if (protocolIs(kurl, "javascript")) { + // Never run javascript while loading is deferred. + if (m_page->defersLoading()) { + FrameLoaderClientBlackBerry* frameLoaderClient = static_cast<FrameLoaderClientBlackBerry*>(m_mainFrame->loader()->client()); + frameLoaderClient->setDeferredManualScript(kurl); + } else + m_mainFrame->script()->executeIfJavaScriptURL(kurl, DoNotReplaceDocumentIfJavaScriptURL); + return; + } + + if (isInitial) + NetworkManager::instance()->setInitialURL(kurl); + + ResourceRequest request(kurl, "" /* referrer */); + request.setToken(networkToken); + if (isInitial || mustHandleInternally) + request.setMustHandleInternally(true); + request.setHTTPMethod(method); + request.setCachePolicy(toWebCoreCachePolicy(cachePolicy)); + if (overrideContentType) + request.setOverrideContentType(overrideContentType); + + if (data) + request.setHTTPBody(FormData::create(data, dataLength)); + + for (unsigned i = 0; i + 1 < headersLength; i += 2) + request.addHTTPHeaderField(headers[i], headers[i + 1]); + + if (forceDownload) + request.setForceDownload(true); + + m_mainFrame->loader()->load(request, "" /* name */, false); +} + +void WebPagePrivate::loadString(const char* string, const char* baseURL, const char* contentType, const char* failingURL) +{ + KURL kurl = parseUrl(baseURL); + ResourceRequest request(kurl); + WTF::RefPtr<SharedBuffer> buffer + = SharedBuffer::create(string, strlen(string)); + SubstituteData substituteData(buffer, + extractMIMETypeFromMediaType(contentType), + extractCharsetFromMediaType(contentType), + failingURL ? parseUrl(failingURL) : KURL()); + m_mainFrame->loader()->load(request, substituteData, false); +} + +bool WebPagePrivate::executeJavaScript(const char* script, JavaScriptDataType& returnType, WebString& returnValue) +{ + ScriptValue result = m_mainFrame->script()->executeScript(String::fromUTF8(script), false); + JSC::JSValue value = result.jsValue(); + if (!value) { + returnType = JSException; + return false; + } + + JSC::ExecState* exec = m_mainFrame->script()->globalObject(mainThreadNormalWorld())->globalExec(); + JSGlobalContextRef context = toGlobalRef(exec); + + JSType type = JSValueGetType(context, toRef(exec, value)); + + switch (type) { + case kJSTypeNull: + returnType = JSNull; + break; + case kJSTypeBoolean: + returnType = JSBoolean; + break; + case kJSTypeNumber: + returnType = JSNumber; + break; + case kJSTypeString: + returnType = JSString; + break; + case kJSTypeObject: + returnType = JSObject; + break; + case kJSTypeUndefined: + default: + returnType = JSUndefined; + break; + } + + if (returnType == JSBoolean || returnType == JSNumber || returnType == JSString || returnType == JSObject) { + String str = result.toString(exec); + returnValue = WebString(str.impl()); + } + + return true; +} + +bool WebPagePrivate::executeJavaScriptInIsolatedWorld(const ScriptSourceCode& sourceCode, JavaScriptDataType& returnType, WebString& returnValue) +{ + if (!m_isolatedWorld) + m_isolatedWorld = m_mainFrame->script()->createWorld(); + + // Use evaluateInWorld to avoid canExecuteScripts check. + ScriptValue result = m_mainFrame->script()->evaluateInWorld(sourceCode, m_isolatedWorld.get()); + JSC::JSValue value = result.jsValue(); + if (!value) { + returnType = JSException; + return false; + } + + JSC::ExecState* exec = m_mainFrame->script()->globalObject(m_isolatedWorld.get())->globalExec(); + JSGlobalContextRef context = toGlobalRef(exec); + + JSType type = JSValueGetType(context, toRef(exec, value)); + + switch (type) { + case kJSTypeNull: + returnType = JSNull; + break; + case kJSTypeBoolean: + returnType = JSBoolean; + break; + case kJSTypeNumber: + returnType = JSNumber; + break; + case kJSTypeString: + returnType = JSString; + break; + case kJSTypeObject: + returnType = JSObject; + break; + case kJSTypeUndefined: + default: + returnType = JSUndefined; + break; + } + + if (returnType == JSBoolean || returnType == JSNumber || returnType == JSString || returnType == JSObject) { + String str = result.toString(exec); + returnValue = WebString(str.impl()); + } + + return true; +} + +void WebPagePrivate::stopCurrentLoad() +{ + // This function should contain all common code triggered by WebPage::load + // (which stops any load in progress before starting the new load) and + // WebPage::stoploading (the entry point for the client to stop the load + // explicitly). If it should only be done while stopping the load + // explicitly, it goes in WebPage::stopLoading, not here. + m_mainFrame->loader()->stopAllLoaders(); + + // Cancel any deferred script that hasn't been processed yet. + FrameLoaderClientBlackBerry* frameLoaderClient = static_cast<FrameLoaderClientBlackBerry*>(m_mainFrame->loader()->client()); + frameLoaderClient->setDeferredManualScript(KURL()); +} + +static void closeURLRecursively(Frame* frame) +{ + // Do not create more frame please. + FrameLoaderClientBlackBerry* frameLoaderClient = static_cast<FrameLoaderClientBlackBerry*>(frame->loader()->client()); + frameLoaderClient->suppressChildFrameCreation(); + + frame->loader()->closeURL(); + + Vector<RefPtr<Frame>, 10> childFrames; + + for (RefPtr<Frame> childFrame = frame->tree()->firstChild(); childFrame; childFrame = childFrame->tree()->nextSibling()) + childFrames.append(childFrame); + + unsigned size = childFrames.size(); + for (unsigned i = 0; i < size; i++) + closeURLRecursively(childFrames[i].get()); +} + +void WebPagePrivate::prepareToDestroy() +{ + // Before the client starts tearing itself down, dispatch the unload event + // so it can take effect while all the client's state (e.g. scroll position) + // is still present. + closeURLRecursively(m_mainFrame); +} + +void WebPagePrivate::setLoadState(LoadState state) +{ + if (m_loadState == state) + return; + + bool isFirstLoad = m_loadState == None; + + // See RIM Bug #1068. + if (state == Finished && m_mainFrame && m_mainFrame->document()) + m_mainFrame->document()->updateStyleIfNeeded(); + + m_loadState = state; + +#if DEBUG_WEBPAGE_LOAD + Platform::log(Platform::LogLevelInfo, "WebPagePrivate::setLoadState %d", state); +#endif + + switch (m_loadState) { + case Provisional: + if (isFirstLoad) { + // Paints the visible backingstore as white to prevent initial checkerboard on + // the first blit. + if (m_backingStore->d->renderVisibleContents() && !m_backingStore->d->isSuspended() && !m_backingStore->d->shouldDirectRenderingToWindow()) + m_backingStore->d->blitVisibleContents(); + } + break; + case Committed: + { + unscheduleZoomAboutPoint(); + +#if ENABLE(SKIA_GPU_CANVAS) + if (m_page->settings()->canvasUsesAcceleratedDrawing()) { + // Free GPU resources as we're on a new page. + // This will help us to free memory pressure. + Platform::Graphics::makeSharedResourceContextCurrent(Platform::Graphics::GLES2); + GrContext* grContext = Platform::Graphics::getGrContext(); + grContext->freeGpuResources(); + } +#endif + +#if USE(ACCELERATED_COMPOSITING) + // FIXME: compositor may only be touched on the compositing thread. + // However, it's created/destroyed by a sync command so this is harmless. + if (m_compositor) { + m_compositor->setLayoutRectForCompositing(IntRect()); + m_compositor->setContentsSizeForCompositing(IntSize()); + } +#endif + m_previousContentsSize = IntSize(); + m_backingStore->d->resetRenderQueue(); + m_backingStore->d->resetTiles(true /* resetBackground */); + m_backingStore->d->setScrollingOrZooming(false, false /* shouldBlit */); + m_userPerformedManualZoom = false; + m_userPerformedManualScroll = false; + m_shouldUseFixedDesktopMode = false; + if (m_resetVirtualViewportOnCommitted) { // For DRT. + m_virtualViewportWidth = 0; + m_virtualViewportHeight = 0; + } + if (m_webSettings->viewportWidth() > 0) { + m_virtualViewportWidth = m_webSettings->viewportWidth(); + m_virtualViewportHeight = m_defaultLayoutSize.height(); + } + // Check if we have already process the meta viewport tag, this only happens on history navigation + if (!m_didRestoreFromPageCache) { + m_viewportArguments = ViewportArguments(); + m_userScalable = m_webSettings->isUserScalable(); + resetScales(); + } else { + IntSize virtualViewport = recomputeVirtualViewportFromViewportArguments(); + m_webPage->setVirtualViewportSize(virtualViewport.width(), virtualViewport.height()); + } + +#if ENABLE(EVENT_MODE_METATAGS) + didReceiveCursorEventMode(ProcessedCursorEvents); + didReceiveTouchEventMode(ProcessedTouchEvents); +#endif + + // If it's a outmost SVG document, we use FixedDesktop mode, otherwise + // we default to Mobile mode. For example, using FixedDesktop mode to + // render http://www.croczilla.com/bits_and_pieces/svg/samples/tiger/tiger.svg + // is user-experience friendly. + if (m_page->mainFrame()->document()->isSVGDocument()) { + setShouldUseFixedDesktopMode(true); + setViewMode(FixedDesktop); + } else + setViewMode(Mobile); + + // Reset block zoom and reflow. + resetBlockZoom(); +#if ENABLE(VIEWPORT_REFLOW) + toggleTextReflowIfEnabledForBlockZoomOnly(); +#endif + + // Set the scroll to origin here and notify the client since we'll be + // zooming below without any real contents yet thus the contents size + // we report to the client could make our current scroll position invalid. + setScrollPosition(IntPoint::zero()); + notifyTransformedScrollChanged(); + + // Paints the visible backingstore as white. Note it is important we do + // this strictly after re-setting the scroll position to origin and resetting + // the scales otherwise the visible contents calculation is wrong and we + // can end up blitting artifacts instead. See: RIM Bug #401. + if (m_backingStore->d->renderVisibleContents() && !m_backingStore->d->isSuspended() && !m_backingStore->d->shouldDirectRenderingToWindow()) + m_backingStore->d->blitVisibleContents(); + + zoomToInitialScaleOnLoad(); + + // Update cursor status. + updateCursor(); + +#if USE(ACCELERATED_COMPOSITING) + // Don't render compositing contents from previous page. + resetCompositingSurface(); +#endif + break; + } + case Finished: + case Failed: + // Notify client of the initial zoom change. + m_client->zoomChanged(m_webPage->isMinZoomed(), m_webPage->isMaxZoomed(), !shouldZoomOnEscape(), currentScale()); + m_backingStore->d->updateTiles(true /* updateVisible */, false /* immediate */); + break; + default: + break; + } +} + +double WebPagePrivate::clampedScale(double scale) const +{ + if (scale < minimumScale()) + return minimumScale(); + if (scale > maximumScale()) + return maximumScale(); + return scale; +} + +bool WebPagePrivate::shouldZoomAboutPoint(double scale, const FloatPoint&, bool enforceScaleClamping, double* clampedScale) +{ + if (!m_mainFrame->view()) + return false; + + if (enforceScaleClamping) + scale = this->clampedScale(scale); + + ASSERT(clampedScale); + *clampedScale = scale; + + if (currentScale() == scale) { + // Make sure backingstore updates resume from pinch zoom in the case where the final zoom level doesn't change. + m_backingStore->d->resumeScreenAndBackingStoreUpdates(BackingStore::None); + m_client->zoomChanged(m_webPage->isMinZoomed(), m_webPage->isMaxZoomed(), !shouldZoomOnEscape(), currentScale()); + return false; + } + + return true; +} + +bool WebPagePrivate::zoomAboutPoint(double unclampedScale, const FloatPoint& anchor, bool enforceScaleClamping, bool forceRendering, bool isRestoringZoomLevel) +{ + if (!isRestoringZoomLevel) { + // Clear any existing block zoom. (If we are restoring a saved zoom level on page load, + // there is guaranteed to be no existing block zoom and we don't want to clear m_shouldReflowBlock.) + resetBlockZoom(); + } + + // The reflow and block zoom stuff here needs to happen regardless of + // whether we shouldZoomAboutPoint. +#if ENABLE(VIEWPORT_REFLOW) + toggleTextReflowIfEnabledForBlockZoomOnly(m_shouldReflowBlock); + if (m_page->settings()->isTextReflowEnabled() && m_mainFrame->view()) + setNeedsLayout(); +#endif + + double scale; + if (!shouldZoomAboutPoint(unclampedScale, anchor, enforceScaleClamping, &scale)) { + if (m_webPage->settings()->textReflowMode() == WebSettings::TextReflowEnabled) { + m_currentPinchZoomNode = 0; + m_anchorInNodeRectRatio = FloatPoint(-1, -1); + } + return false; + } + TransformationMatrix zoom; + zoom.scale(scale); + +#if DEBUG_WEBPAGE_LOAD + if (loadState() < Finished) + Platform::log(Platform::LogLevelInfo, "WebPagePrivate::zoomAboutPoint scale %f anchor (%f, %f)", scale, anchor.x(), anchor.y()); +#endif + + // Our current scroll position in float. + FloatPoint scrollPosition = this->scrollPosition(); + + // Anchor offset from scroll position in float. + FloatPoint anchorOffset(anchor.x() - scrollPosition.x(), anchor.y() - scrollPosition.y()); + + // The horizontal scaling factor and vertical scaling factor should be equal + // to preserve aspect ratio of content. + ASSERT(m_transformationMatrix->m11() == m_transformationMatrix->m22()); + + // Need to invert the previous transform to anchor the viewport. + double inverseScale = scale / m_transformationMatrix->m11(); + + // Actual zoom. + *m_transformationMatrix = zoom; + + // Suspend all screen updates to the backingstore. + m_backingStore->d->suspendScreenAndBackingStoreUpdates(); + + updateViewportSize(); + + IntPoint newScrollPosition(IntPoint(max(0, static_cast<int>(roundf(anchor.x() - anchorOffset.x() / inverseScale))), + max(0, static_cast<int>(roundf(anchor.y() - anchorOffset.y() / inverseScale))))); + + if (m_webPage->settings()->textReflowMode() == WebSettings::TextReflowEnabled) { + // This is a hack for email which has reflow always turned on. + m_mainFrame->view()->setNeedsLayout(); + requestLayoutIfNeeded(); + if (m_currentPinchZoomNode) + newScrollPosition = calculateReflowedScrollPosition(anchorOffset, scale == minimumScale() ? 1 : inverseScale); + m_currentPinchZoomNode = 0; + m_anchorInNodeRectRatio = FloatPoint(-1, -1); + } + + setScrollPosition(newScrollPosition); + + notifyTransformChanged(); + + bool isLoading = this->isLoading(); + + // We need to invalidate all tiles both visible and non-visible if we're loading. + m_backingStore->d->updateTiles(isLoading /* updateVisible */, false /* immediate */); + + m_client->resetBitmapZoomScale(m_transformationMatrix->m11()); + + bool shouldRender = !isLoading || m_userPerformedManualZoom || forceRendering; + bool shouldClearVisibleZoom = isLoading && shouldRender; + + if (shouldClearVisibleZoom) { + // If we are loading and rendering then we need to clear the render queue's + // visible zoom jobs as they will be irrelevant with the render below. + m_backingStore->d->clearVisibleZoom(); + } + + // Clear window to make sure there are no artifacts. + if (shouldRender) { + m_backingStore->d->clearWindow(); + // Resume all screen updates to the backingstore and render+blit visible contents to screen. + m_backingStore->d->resumeScreenAndBackingStoreUpdates(BackingStore::RenderAndBlit); + } else { + // Resume all screen updates to the backingstore but do not blit to the screen because we not rendering. + m_backingStore->d->resumeScreenAndBackingStoreUpdates(BackingStore::None); + } + + m_client->zoomChanged(m_webPage->isMinZoomed(), m_webPage->isMaxZoomed(), !shouldZoomOnEscape(), currentScale()); + + return true; +} + +IntPoint WebPagePrivate::calculateReflowedScrollPosition(const FloatPoint& anchorOffset, double inverseScale) +{ + // Should only be invoked when text reflow is enabled. + ASSERT(m_webPage->settings()->textReflowMode() == WebSettings::TextReflowEnabled); + + int offsetY = 0; + int offsetX = 0; + + IntRect nodeRect = rectForNode(m_currentPinchZoomNode.get()); + + if (m_currentPinchZoomNode->renderer() && m_anchorInNodeRectRatio.y() >= 0) { + offsetY = nodeRect.height() * m_anchorInNodeRectRatio.y(); + if (m_currentPinchZoomNode->renderer()->isImage() && m_anchorInNodeRectRatio.x() > 0) + offsetX = nodeRect.width() * m_anchorInNodeRectRatio.x() - anchorOffset.x() / inverseScale; + } + + IntRect reflowedRect = adjustRectOffsetForFrameOffset(nodeRect, m_currentPinchZoomNode.get()); + + return IntPoint(max(0, static_cast<int>(roundf(reflowedRect.x() + offsetX))), + max(0, static_cast<int>(roundf(reflowedRect.y() + offsetY - anchorOffset.y() / inverseScale)))); +} + +bool WebPagePrivate::scheduleZoomAboutPoint(double unclampedScale, const FloatPoint& anchor, bool enforceScaleClamping, bool forceRendering) +{ + double scale; + if (!shouldZoomAboutPoint(unclampedScale, anchor, enforceScaleClamping, &scale)) { + // We could be back to the right zoom level before the timer has + // timed out, because of wiggling back and forth. Stop the timer. + unscheduleZoomAboutPoint(); + return false; + } + + // For some reason, the bitmap zoom wants an anchor in backingstore coordinates! + // this is different from zoomAboutPoint, which wants content coordinates. + // See RIM Bug #641. + + FloatPoint transformedAnchor = mapToTransformedFloatPoint(anchor); + FloatPoint transformedScrollPosition = mapToTransformedFloatPoint(scrollPosition()); + + // Prohibit backingstore from updating the window overtop of the bitmap. + m_backingStore->d->suspendScreenAndBackingStoreUpdates(); + + // Need to invert the previous transform to anchor the viewport. + double zoomFraction = scale / transformationMatrix()->m11(); + + // Anchor offset from scroll position in float. + FloatPoint anchorOffset(transformedAnchor.x() - transformedScrollPosition.x(), + transformedAnchor.y() - transformedScrollPosition.y()); + + IntPoint srcPoint( + static_cast<int>(roundf(transformedAnchor.x() - anchorOffset.x() / zoomFraction)), + static_cast<int>(roundf(transformedAnchor.y() - anchorOffset.y() / zoomFraction))); + + const IntRect viewportRect = IntRect(IntPoint::zero(), transformedViewportSize()); + const IntRect dstRect = viewportRect; + + // This is the rect to pass as the actual source rect in the backingstore + // for the transform given by zoom. + IntRect srcRect(srcPoint.x(), + srcPoint.y(), + viewportRect.width() / zoomFraction, + viewportRect.height() / zoomFraction); + m_backingStore->d->blitContents(dstRect, srcRect); + + m_delayedZoomArguments.scale = scale; + m_delayedZoomArguments.anchor = anchor; + m_delayedZoomArguments.enforceScaleClamping = enforceScaleClamping; + m_delayedZoomArguments.forceRendering = forceRendering; + m_delayedZoomTimer->startOneShot(delayedZoomInterval); + + return true; +} + +void WebPagePrivate::unscheduleZoomAboutPoint() +{ + if (m_delayedZoomTimer->isActive()) + m_backingStore->d->resumeScreenAndBackingStoreUpdates(BackingStore::None); + + m_delayedZoomTimer->stop(); +} + +void WebPagePrivate::zoomAboutPointTimerFired(Timer<WebPagePrivate>*) +{ + zoomAboutPoint(m_delayedZoomArguments.scale, m_delayedZoomArguments.anchor, m_delayedZoomArguments.enforceScaleClamping, m_delayedZoomArguments.forceRendering); +} + +void WebPagePrivate::setNeedsLayout() +{ + FrameView* view = m_mainFrame->view(); + ASSERT(view); + view->setNeedsLayout(); +} + +void WebPagePrivate::requestLayoutIfNeeded() const +{ + FrameView* view = m_mainFrame->view(); + ASSERT(view); + view->updateLayoutAndStyleIfNeededRecursive(); + ASSERT(!view->needsLayout()); +} + +IntPoint WebPagePrivate::scrollPosition() const +{ + return m_backingStoreClient->scrollPosition(); +} + +IntPoint WebPagePrivate::maximumScrollPosition() const +{ + return m_backingStoreClient->maximumScrollPosition(); +} + +void WebPagePrivate::setScrollPosition(const IntPoint& pos) +{ + m_backingStoreClient->setScrollPosition(pos); +} + +bool WebPagePrivate::shouldSendResizeEvent() +{ + if (!m_mainFrame->document()) + return false; + + // PR#96865 : Provide an option to always send resize events, regardless of the loading + // status. The scenario for this are Sapphire applications which tend to + // maintain an open GET request to the server. This open GET results in + // webkit thinking that content is still arriving when at the application + // level it is considered fully loaded. + // + // NOTE: Care must be exercised in the use of this option, as it bypasses + // the sanity provided in 'isLoadingInAPISense()' below. + // + static const bool unrestrictedResizeEvents = Platform::Settings::get()->unrestrictedResizeEvents(); + if (unrestrictedResizeEvents) + return true; + + // Don't send the resize event if the document is loading. Some pages automatically reload + // when the window is resized; Safari on iPhone often resizes the window while setting up its + // viewport. This obviously can cause problems. + DocumentLoader* documentLoader = m_mainFrame->loader()->documentLoader(); + if (documentLoader && documentLoader->isLoadingInAPISense()) + return false; + + return true; +} + +void WebPagePrivate::willDeferLoading() +{ + m_client->willDeferLoading(); +} + +void WebPagePrivate::didResumeLoading() +{ + m_client->didResumeLoading(); +} + +bool WebPage::scrollBy(const Platform::IntSize& delta, bool scrollMainFrame) +{ + d->m_backingStoreClient->setIsClientGeneratedScroll(true); + bool b = d->scrollBy(delta.width(), delta.height(), scrollMainFrame); + d->m_backingStoreClient->setIsClientGeneratedScroll(false); + return b; +} + +bool WebPagePrivate::scrollBy(int deltaX, int deltaY, bool scrollMainFrame) +{ + IntSize delta(deltaX, deltaY); + if (!scrollMainFrame) { + // We need to work around the fact that ::map{To,From}Transformed do not + // work well with negative values, like a negative width or height of an IntSize. + IntSize copiedDelta(IntSize(abs(delta.width()), abs(delta.height()))); + IntSize untransformedCopiedDelta = mapFromTransformed(copiedDelta); + delta = IntSize( + delta.width() < 0 ? -untransformedCopiedDelta.width() : untransformedCopiedDelta.width(), + delta.height() < 0 ? -untransformedCopiedDelta.height(): untransformedCopiedDelta.height()); + + if (m_inRegionScrollStartingNode) { + if (scrollNodeRecursively(m_inRegionScrollStartingNode.get(), delta)) { + m_selectionHandler->selectionPositionChanged(); + // FIXME: We have code in place to handle scrolling and clipping tap highlight + // on in-region scrolling. As soon as it is fast enough (i.e. we have it backed by + // a backing store), we can reliably make use of it in the real world. + // m_touchEventHandler->drawTapHighlight(); + return true; + } + } + + return false; + } + + setScrollPosition(scrollPosition() + delta); + return true; +} + +void WebPage::notifyInRegionScrollStatusChanged(bool status) +{ + d->notifyInRegionScrollStatusChanged(status); +} + +void WebPagePrivate::notifyInRegionScrollStatusChanged(bool status) +{ + if (!status && m_inRegionScrollStartingNode) { + enqueueRenderingOfClippedContentOfScrollableNodeAfterInRegionScrolling(m_inRegionScrollStartingNode.get()); + m_inRegionScrollStartingNode = 0; + } +} + +void WebPagePrivate::enqueueRenderingOfClippedContentOfScrollableNodeAfterInRegionScrolling(Node* scrolledNode) +{ + ASSERT(scrolledNode); + if (scrolledNode->isDocumentNode()) { + Frame* frame = static_cast<const Document*>(scrolledNode)->frame(); + ASSERT(frame); + if (!frame) + return; + ASSERT(frame != m_mainFrame); + FrameView* view = frame->view(); + if (!view) + return; + + // Steps: + // #1 - Get frame rect in contents coords. + // #2 - Get the clipped scrollview rect in contents coords. + // #3 - Take transform into account for 1 and 2. + // #4 - Subtract 2 from 1, so we know exactly which areas of the frame + // are offscreen, and need async repainting. + FrameView* mainFrameView = m_mainFrame->view(); + ASSERT(mainFrameView); + IntRect frameRect = view->frameRect(); + frameRect = frame->tree()->parent()->view()->contentsToWindow(frameRect); + frameRect = mainFrameView->windowToContents(frameRect); + + IntRect visibleWindowRect = getRecursiveVisibleWindowRect(view); + IntRect visibleContentsRect = mainFrameView->windowToContents(visibleWindowRect); + + IntRect transformedFrameRect = mapToTransformed(frameRect); + IntRect transformedVisibleContentsRect = mapToTransformed(visibleContentsRect); + + Platform::IntRectRegion offscreenRegionOfIframe + = Platform::IntRectRegion::subtractRegions(Platform::IntRect(transformedFrameRect), Platform::IntRect(transformedVisibleContentsRect)); + + if (!offscreenRegionOfIframe.isEmpty()) + m_backingStore->d->m_renderQueue->addToQueue(RenderQueue::RegularRender, offscreenRegionOfIframe.rects()); + } +} + +void WebPagePrivate::setHasInRegionScrollableAreas(bool b) +{ + if (b != m_hasInRegionScrollableAreas) + m_hasInRegionScrollableAreas = b; +} + +IntSize WebPagePrivate::viewportSize() const +{ + return mapFromTransformed(transformedViewportSize()); +} + +IntSize WebPagePrivate::actualVisibleSize() const +{ + return mapFromTransformed(transformedActualVisibleSize()); +} + +bool WebPagePrivate::hasVirtualViewport() const +{ + return m_virtualViewportWidth && m_virtualViewportHeight; +} + +void WebPagePrivate::updateViewportSize(bool setFixedReportedSize, bool sendResizeEvent) +{ + ASSERT(m_mainFrame->view()); + if (setFixedReportedSize) + m_mainFrame->view()->setFixedReportedSize(actualVisibleSize()); + + IntRect frameRect = IntRect(scrollPosition(), viewportSize()); + if (frameRect != m_mainFrame->view()->frameRect()) { + m_mainFrame->view()->setFrameRect(frameRect); + m_mainFrame->view()->adjustViewSize(); + } + + // We're going to need to send a resize event to JavaScript because + // innerWidth and innerHeight depend on fixed reported size. + // This is how we support mobile pages where JavaScript resizes + // the page in order to get around the fixed layout size, e.g. + // google maps when it detects a mobile user agent. + if (sendResizeEvent && shouldSendResizeEvent()) + m_mainFrame->eventHandler()->sendResizeEvent(); + + // When the actual visible size changes, we also + // need to reposition fixed elements. + m_mainFrame->view()->repaintFixedElementsAfterScrolling(); +} + +FloatPoint WebPagePrivate::centerOfVisibleContentsRect() const +{ + // The visible contents rect in float. + FloatRect visibleContentsRect = this->visibleContentsRect(); + + // The center of the visible contents rect in float. + return FloatPoint(visibleContentsRect.x() + visibleContentsRect.width() / 2.0, + visibleContentsRect.y() + visibleContentsRect.height() / 2.0); +} + +IntRect WebPagePrivate::visibleContentsRect() const +{ + return m_backingStoreClient->visibleContentsRect(); +} + +IntSize WebPagePrivate::contentsSize() const +{ + if (!m_mainFrame->view()) + return IntSize(); + + return m_backingStoreClient->contentsSize(); +} + +IntSize WebPagePrivate::absoluteVisibleOverflowSize() const +{ + if (!m_mainFrame->contentRenderer()) + return IntSize(); + + return IntSize(m_mainFrame->contentRenderer()->rightAbsoluteVisibleOverflow(), m_mainFrame->contentRenderer()->bottomAbsoluteVisibleOverflow()); +} + +void WebPagePrivate::contentsSizeChanged(const IntSize& contentsSize) +{ + if (m_previousContentsSize == contentsSize) + return; + + // This should only occur in the middle of layout so we set a flag here and + // handle it at the end of the layout. + m_contentsSizeChanged = true; + +#if DEBUG_WEBPAGE_LOAD + Platform::log(Platform::LogLevelInfo, "WebPagePrivate::contentsSizeChanged %dx%d", contentsSize.width(), contentsSize.height()); +#endif +} + +void WebPagePrivate::layoutFinished() +{ + if (!m_contentsSizeChanged && !m_overflowExceedsContentsSize) + return; + + m_contentsSizeChanged = false; // Toggle to turn off notification again. + m_overflowExceedsContentsSize = false; + + if (contentsSize().isEmpty()) + return; + + // The call to zoomToInitialScaleOnLoad can cause recursive layout when called from + // the middle of a layout, but the recursion is limited by detection code in + // setViewMode() and mitigation code in fixedLayoutSize(). + if (didLayoutExceedMaximumIterations()) { + notifyTransformedContentsSizeChanged(); + return; + } + + // Temporarily save the m_previousContentsSize here before updating it (in + // notifyTransformedContentsSizeChanged()) so we can compare if our contents + // shrunk afterwards. + IntSize previousContentsSize = m_previousContentsSize; + + m_nestedLayoutFinishedCount++; + + if (loadState() == Committed) + zoomToInitialScaleOnLoad(); + else if (loadState() != None) + notifyTransformedContentsSizeChanged(); + + m_nestedLayoutFinishedCount--; + + if (!m_nestedLayoutFinishedCount) { + // When the contents shrinks, there is a risk that we + // will be left at a scroll position that lies outside of the + // contents rect. Since we allow overscrolling and neglect + // to clamp overscroll in order to retain input focus (RIM Bug #414) + // we need to clamp somewhere, and this is where we know the + // contents size has changed. + + if (contentsSize() != previousContentsSize) { + + IntPoint newScrollPosition = scrollPosition(); + + if (contentsSize().height() < previousContentsSize.height()) { + IntPoint scrollPositionWithHeightShrunk = IntPoint(newScrollPosition.x(), maximumScrollPosition().y()); + newScrollPosition = newScrollPosition.shrunkTo(scrollPositionWithHeightShrunk); + } + + if (contentsSize().width() < previousContentsSize.width()) { + IntPoint scrollPositionWithWidthShrunk = IntPoint(maximumScrollPosition().x(), newScrollPosition.y()); + newScrollPosition = newScrollPosition.shrunkTo(scrollPositionWithWidthShrunk); + } + + if (newScrollPosition != scrollPosition()) { + setScrollPosition(newScrollPosition); + notifyTransformedScrollChanged(); + } + } + } +} + +void WebPagePrivate::zoomToInitialScaleOnLoad() +{ +#if DEBUG_WEBPAGE_LOAD + Platform::log(Platform::LogLevelInfo, "WebPagePrivate::zoomToInitialScaleOnLoad"); +#endif + + bool needsLayout = false; + + // If the contents width exceeds the viewport width set to desktop mode. + if (m_shouldUseFixedDesktopMode) + needsLayout = setViewMode(FixedDesktop); + else + needsLayout = setViewMode(Desktop); + + if (needsLayout) { + // This can cause recursive layout... + setNeedsLayout(); + } + + if (contentsSize().isEmpty()) { +#if DEBUG_WEBPAGE_LOAD + Platform::log(Platform::LogLevelInfo, "WebPagePrivate::zoomToInitialScaleOnLoad content is empty!"); +#endif + requestLayoutIfNeeded(); + m_client->resetBitmapZoomScale(currentScale()); + notifyTransformedContentsSizeChanged(); + return; + } + + bool performedZoom = false; + bool shouldZoom = !m_userPerformedManualZoom; + + // If this load should restore view state, don't zoom to initial scale + // but instead let the HistoryItem's saved viewport reign supreme. + if (m_mainFrame && m_mainFrame->loader() && m_mainFrame->loader()->shouldRestoreScrollPositionAndViewState()) + shouldZoom = false; + + if (shouldZoom && loadState() == Committed) { + // Preserve at top and at left position, to avoid scrolling + // to a non top-left position for web page with viewport meta tag + // that specifies an initial-scale that is zoomed in. + FloatPoint anchor = centerOfVisibleContentsRect(); + if (!scrollPosition().x()) + anchor.setX(0); + if (!scrollPosition().y()) + anchor.setY(0); + performedZoom = zoomAboutPoint(initialScale(), anchor); + } + + // zoomAboutPoint above can also toggle setNeedsLayout and cause recursive layout... + requestLayoutIfNeeded(); + + if (!performedZoom) { + // We only notify if we didn't perform zoom, because zoom will notify on + // its own... + m_client->resetBitmapZoomScale(currentScale()); + notifyTransformedContentsSizeChanged(); + } +} + +double WebPagePrivate::zoomToFitScale() const +{ + // We must clamp the contents for this calculation so that we do not allow an + // arbitrarily small zoomToFitScale much like we clamp the fixedLayoutSize() + // so that we do not have arbitrarily large layout size. + // If we have a specified viewport, we may need to be able to zoom out more. + int contentWidth = std::min(contentsSize().width(), std::max(m_virtualViewportWidth, static_cast<int>(defaultMaxLayoutSize().width()))); + + // defaultMaxLayoutSize().width() is a safeguard for excessively large page layouts that + // is too restrictive for image documents. In this case, the document width is sufficient. + Document* doc = m_page->mainFrame()->document(); + if (doc && doc->isImageDocument()) + contentWidth = contentsSize().width(); + + // If we have a virtual viewport and its aspect ratio caused content to layout + // wider than the default layout aspect ratio we need to zoom to fit the content height + // in order to avoid showing a grey area below the web page. + // Without virtual viewport we can never get into this situation. + if (hasVirtualViewport()) { + int contentHeight = std::min(contentsSize().height(), std::max(m_virtualViewportHeight, static_cast<int>(defaultMaxLayoutSize().height()))); + + // Aspect ratio check without division. + if (contentWidth * m_defaultLayoutSize.height() > contentHeight * m_defaultLayoutSize.width()) + return contentHeight > 0 ? static_cast<double>(m_defaultLayoutSize.height()) / contentHeight : 1.0; + } + + return contentWidth > 0.0 ? static_cast<double>(m_actualVisibleWidth) / contentWidth : 1.0; +} + +double WebPagePrivate::initialScale() const +{ + if (m_initialScale > 0.0) + return m_initialScale; + + if (m_webSettings->isZoomToFitOnLoad()) + return zoomToFitScale(); + + return 1.0; +} + +void WebPage::initializeIconDataBase() +{ + IconDatabaseClientBlackBerry::getInstance()->initIconDatabase(d->m_webSettings); +} + +bool WebPage::isUserScalable() const +{ + return d->isUserScalable(); +} + +double WebPage::currentScale() const +{ + return d->currentScale(); +} + +double WebPage::initialScale() const +{ + return d->initialScale(); +} + +double WebPage::zoomToFitScale() const +{ + return d->zoomToFitScale(); +} + +void WebPage::setInitialScale(double initialScale) +{ + d->setInitialScale(initialScale); +} + +double WebPage::minimumScale() const +{ + return d->minimumScale(); +} + +void WebPage::setMinimumScale(double minimumScale) +{ + d->setMinimumScale(minimumScale); +} + +double WebPage::maximumScale() const +{ + return d->maximumScale(); +} + +void WebPage::setMaximumScale(double maximumScale) +{ + d->setMaximumScale(maximumScale); +} + +double WebPagePrivate::maximumScale() const +{ + if (m_maximumScale >= zoomToFitScale() && m_maximumScale >= m_minimumScale) + return m_maximumScale; + + return hasVirtualViewport() ? std::max<double>(zoomToFitScale(), 4.0) : 4.0; +} + +void WebPagePrivate::resetScales() +{ + TransformationMatrix identity; + *m_transformationMatrix = identity; + m_initialScale = m_webSettings->initialScale() > 0 ? m_webSettings->initialScale() : -1.0; + m_minimumScale = -1.0; + m_maximumScale = -1.0; + + // We have to let WebCore know about updated framerect now that we've + // reset our scales. See: RIM Bug #401. + updateViewportSize(); +} + +IntPoint WebPagePrivate::transformedScrollPosition() const +{ + return m_backingStoreClient->transformedScrollPosition(); +} + +IntPoint WebPagePrivate::transformedMaximumScrollPosition() const +{ + return m_backingStoreClient->transformedMaximumScrollPosition(); +} + +IntSize WebPagePrivate::transformedActualVisibleSize() const +{ + return IntSize(m_actualVisibleWidth, m_actualVisibleHeight); +} + +IntSize WebPagePrivate::transformedViewportSize() const +{ + return Platform::Graphics::Screen::size(); +} + +IntRect WebPagePrivate::transformedVisibleContentsRect() const +{ + // Usually this would be mapToTransformed(visibleContentsRect()), but + // that results in rounding errors because we already set the WebCore + // viewport size from our original transformedViewportSize(). + // Instead, we only transform the scroll position and take the + // viewport size as it is, which ensures that e.g. blitting operations + // always cover the whole widget/screen. + return IntRect(transformedScrollPosition(), transformedViewportSize()); +} + +IntSize WebPagePrivate::transformedContentsSize() const +{ + // mapToTransformed() functions use this method to crop their results, + // so we can't make use of them here. While we want rounding inside page + // boundaries to extend rectangles and round points, we need to crop the + // contents size to the floored values so that we don't try to display + // or report points that are not fully covered by the actual float-point + // contents rectangle. + const IntSize untransformedContentsSize = contentsSize(); + const FloatPoint transformedBottomRight = m_transformationMatrix->mapPoint( + FloatPoint(untransformedContentsSize.width(), untransformedContentsSize.height())); + return IntSize(floorf(transformedBottomRight.x()), floorf(transformedBottomRight.y())); +} + +IntPoint WebPagePrivate::mapFromContentsToViewport(const IntPoint& point) const +{ + return m_backingStoreClient->mapFromContentsToViewport(point); +} + +IntPoint WebPagePrivate::mapFromViewportToContents(const IntPoint& point) const +{ + return m_backingStoreClient->mapFromViewportToContents(point); +} + +IntRect WebPagePrivate::mapFromContentsToViewport(const IntRect& rect) const +{ + return m_backingStoreClient->mapFromContentsToViewport(rect); +} + +IntRect WebPagePrivate::mapFromViewportToContents(const IntRect& rect) const +{ + return m_backingStoreClient->mapFromViewportToContents(rect); +} + +IntPoint WebPagePrivate::mapFromTransformedContentsToTransformedViewport(const IntPoint& point) const +{ + return m_backingStoreClient->mapFromTransformedContentsToTransformedViewport(point); +} + +IntPoint WebPagePrivate::mapFromTransformedViewportToTransformedContents(const IntPoint& point) const +{ + return m_backingStoreClient->mapFromTransformedViewportToTransformedContents(point); +} + +IntRect WebPagePrivate::mapFromTransformedContentsToTransformedViewport(const IntRect& rect) const +{ + return m_backingStoreClient->mapFromTransformedContentsToTransformedViewport(rect); +} + +IntRect WebPagePrivate::mapFromTransformedViewportToTransformedContents(const IntRect& rect) const +{ + return m_backingStoreClient->mapFromTransformedViewportToTransformedContents(rect); +} + +// NOTE: PIXEL ROUNDING! +// Accurate back-and-forth rounding is not possible with information loss +// by integer points and sizes, so we always expand the resulting mapped +// float rectangles to the nearest integer. For points, we always use +// floor-rounding in mapToTransformed() so that we don't have to crop to +// the (floor'd) transformed contents size. +static inline IntPoint roundTransformedPoint(const FloatPoint &point) +{ + // Maps by rounding half towards zero. + return IntPoint(static_cast<int>(floorf(point.x())), static_cast<int>(floorf(point.y()))); +} + +static inline IntPoint roundUntransformedPoint(const FloatPoint &point) +{ + // Maps by rounding half away from zero. + return IntPoint(static_cast<int>(ceilf(point.x())), static_cast<int>(ceilf(point.y()))); +} + +IntPoint WebPagePrivate::mapToTransformed(const IntPoint& point) const +{ + return roundTransformedPoint(m_transformationMatrix->mapPoint(FloatPoint(point))); +} + +FloatPoint WebPagePrivate::mapToTransformedFloatPoint(const FloatPoint& point) const +{ + return m_transformationMatrix->mapPoint(point); +} + +IntPoint WebPagePrivate::mapFromTransformed(const IntPoint& point) const +{ + return roundUntransformedPoint(m_transformationMatrix->inverse().mapPoint(FloatPoint(point))); +} + +FloatPoint WebPagePrivate::mapFromTransformedFloatPoint(const FloatPoint& point) const +{ + return m_transformationMatrix->inverse().mapPoint(point); +} + +FloatRect WebPagePrivate::mapFromTransformedFloatRect(const FloatRect& rect) const +{ + return m_transformationMatrix->inverse().mapRect(rect); +} + +IntSize WebPagePrivate::mapToTransformed(const IntSize& size) const +{ + return mapToTransformed(IntRect(IntPoint::zero(), size)).size(); +} + +IntSize WebPagePrivate::mapFromTransformed(const IntSize& size) const +{ + return mapFromTransformed(IntRect(IntPoint::zero(), size)).size(); +} + +IntRect WebPagePrivate::mapToTransformed(const IntRect& rect) const +{ + return enclosingIntRect(m_transformationMatrix->mapRect(FloatRect(rect))); +} + +// Use this in conjunction with mapToTransformed(IntRect), in most cases. +void WebPagePrivate::clipToTransformedContentsRect(IntRect& rect) const +{ + rect.intersect(IntRect(IntPoint::zero(), transformedContentsSize())); +} + +IntRect WebPagePrivate::mapFromTransformed(const IntRect& rect) const +{ + return enclosingIntRect(m_transformationMatrix->inverse().mapRect(FloatRect(rect))); +} + +bool WebPagePrivate::transformedPointEqualsUntransformedPoint(const IntPoint& transformedPoint, const IntPoint& untransformedPoint) +{ + // Scaling down is always more accurate than scaling up. + if (m_transformationMatrix->a() > 1.0) + return transformedPoint == mapToTransformed(untransformedPoint); + + return mapFromTransformed(transformedPoint) == untransformedPoint; +} + +void WebPagePrivate::notifyTransformChanged() +{ + notifyTransformedContentsSizeChanged(); + notifyTransformedScrollChanged(); + + m_backingStore->d->transformChanged(); +} + +void WebPagePrivate::notifyTransformedContentsSizeChanged() +{ + // We mark here as the last reported content size we sent to the client. + m_previousContentsSize = contentsSize(); + + const IntSize size = transformedContentsSize(); + m_backingStore->d->contentsSizeChanged(size); + m_client->contentsSizeChanged(size); + m_selectionHandler->selectionPositionChanged(); +} + +void WebPagePrivate::notifyTransformedScrollChanged() +{ + const IntPoint pos = transformedScrollPosition(); + m_backingStore->d->scrollChanged(pos); + m_client->scrollChanged(pos); +} + +bool WebPagePrivate::setViewMode(ViewMode mode) +{ + if (!m_mainFrame->view()) + return false; + + m_viewMode = mode; + + // If we're in the middle of a nested layout with a recursion count above + // some maximum threshold, then our algorithm for finding the minimum content + // width of a given page has become dependent on the visible width. + // + // We need to find some method to ensure that we don't experience excessive + // and even infinite recursion. This can even happen with valid html. The + // former can happen when we run into inline text with few candidates for line + // break. The latter can happen for instance if the page has a negative margin + // set against the right border. Note: this is valid by spec and can lead to + // a situation where there is no value for which the content width will ensure + // no horizontal scrollbar. + // Example: LayoutTests/css1/box_properties/margin.html + // + // In order to address such situations when we detect a recursion above some + // maximum threshold we snap our fixed layout size to a defined quantum increment. + // Eventually, either the content width will be satisfied to ensure no horizontal + // scrollbar or this increment will run into the maximum layout size and the + // recursion will necessarily end. + bool snapToIncrement = didLayoutExceedMaximumIterations(); + + IntSize currentSize = m_mainFrame->view()->fixedLayoutSize(); + IntSize newSize = fixedLayoutSize(snapToIncrement); + if (currentSize == newSize) + return false; + + // FIXME: Temp solution. We'll get back to this. + if (m_nestedLayoutFinishedCount) { + double widthChange = fabs(double(newSize.width() - currentSize.width()) / currentSize.width()); + double heightChange = fabs(double(newSize.height() - currentSize.height()) / currentSize.height()); + if (widthChange < 0.05 && heightChange < 0.05) + return false; + } + + m_mainFrame->view()->setUseFixedLayout(useFixedLayout()); + m_mainFrame->view()->setFixedLayoutSize(newSize); + return true; // Needs re-layout! +} + +void WebPagePrivate::setCursor(PlatformCursorHandle handle) +{ + if (m_currentCursor.type() != handle.type()) { + m_currentCursor = handle; + m_client->cursorChanged(handle.type(), handle.url().c_str(), handle.hotspot().x(), handle.hotspot().y()); + } +} + +Platform::NetworkStreamFactory* WebPagePrivate::networkStreamFactory() +{ + return m_client->networkStreamFactory(); +} + +Platform::Graphics::Window* WebPagePrivate::platformWindow() const +{ + return m_client->window(); +} + +void WebPagePrivate::setPreventsScreenDimming(bool keepAwake) +{ + if (keepAwake) { + if (!m_preventIdleDimmingCount) + m_client->setPreventsScreenIdleDimming(true); + m_preventIdleDimmingCount++; + } else if (m_preventIdleDimmingCount > 0) { + m_preventIdleDimmingCount--; + if (!m_preventIdleDimmingCount) + m_client->setPreventsScreenIdleDimming(false); + } else + ASSERT_NOT_REACHED(); // SetPreventsScreenIdleDimming(false) called too many times. +} + +void WebPagePrivate::showVirtualKeyboard(bool showKeyboard) +{ + m_client->showVirtualKeyboard(showKeyboard); +} + +void WebPagePrivate::ensureContentVisible(bool centerInView) +{ + m_inputHandler->ensureFocusElementVisible(centerInView); +} + +void WebPagePrivate::zoomToContentRect(const IntRect& rect) +{ + // Don't scale if the user is not supposed to scale. + if (!isUserScalable()) + return; + + FloatPoint anchor = FloatPoint(rect.width() / 2.0 + rect.x(), rect.height() / 2.0 + rect.y()); + IntSize viewSize = viewportSize(); + + // Calculate the scale required to scale that dimension to fit. + double scaleH = (double)viewSize.width() / (double)rect.width(); + double scaleV = (double)viewSize.height() / (double)rect.height(); + + // Choose the smaller scale factor so that all of the content is visible. + zoomAboutPoint(min(scaleH, scaleV), anchor); +} + +void WebPagePrivate::registerPlugin(PluginView* plugin, bool shouldRegister) +{ + if (shouldRegister) + m_pluginViews.add(plugin); + else + m_pluginViews.remove(plugin); +} + +#define FOR_EACH_PLUGINVIEW(pluginViews) \ + HashSet<PluginView*>::const_iterator it = pluginViews.begin(); \ + HashSet<PluginView*>::const_iterator last = pluginViews.end(); \ + for (; it != last; ++it) + +void WebPagePrivate::notifyPageOnLoad() +{ + FOR_EACH_PLUGINVIEW(m_pluginViews) + (*it)->handleOnLoadEvent(); +} + +bool WebPagePrivate::shouldPluginEnterFullScreen(PluginView* plugin, const char* windowUniquePrefix) +{ + return m_client->shouldPluginEnterFullScreen(); +} + +void WebPagePrivate::didPluginEnterFullScreen(PluginView* plugin, const char* windowUniquePrefix) +{ + m_fullScreenPluginView = plugin; + m_client->didPluginEnterFullScreen(); + Platform::Graphics::Window::setTransparencyDiscardFilter(windowUniquePrefix); + m_client->window()->setSensitivityFullscreenOverride(true); +} + +void WebPagePrivate::didPluginExitFullScreen(PluginView* plugin, const char* windowUniquePrefix) +{ + m_fullScreenPluginView = 0; + m_client->didPluginExitFullScreen(); + Platform::Graphics::Window::setTransparencyDiscardFilter(0); + m_client->window()->setSensitivityFullscreenOverride(false); +} + +void WebPagePrivate::onPluginStartBackgroundPlay(PluginView* plugin, const char* windowUniquePrefix) +{ + m_client->onPluginStartBackgroundPlay(); +} + +void WebPagePrivate::onPluginStopBackgroundPlay(PluginView* plugin, const char* windowUniquePrefix) +{ + m_client->onPluginStopBackgroundPlay(); +} + +bool WebPagePrivate::lockOrientation(bool landscape) +{ + return m_client->lockOrientation(landscape); +} + +void WebPagePrivate::unlockOrientation() +{ + return m_client->unlockOrientation(); +} + +int WebPagePrivate::orientation() const +{ +#if ENABLE(ORIENTATION_EVENTS) + return m_mainFrame->orientation(); +#else +#error ORIENTATION_EVENTS must be defined. +// Or a copy of the orientation value will have to be stored in these objects. +#endif +} + +double WebPagePrivate::currentZoomFactor() const +{ + return currentScale(); +} + +int WebPagePrivate::showAlertDialog(WebPageClient::AlertType atype) +{ + return m_client->showAlertDialog(atype); +} + +bool WebPagePrivate::isActive() const +{ + return m_client->isActive(); +} + +bool WebPagePrivate::useFixedLayout() const +{ + return true; +} + +ActiveNodeContext WebPagePrivate::activeNodeContext(TargetDetectionStrategy strategy) +{ + ActiveNodeContext context; + + RefPtr<Node> node = contextNode(strategy); + m_currentContextNode = node; + if (!m_currentContextNode) + return context; + + requestLayoutIfNeeded(); + + bool nodeAllowSelectionOverride = false; + if (Node* linkNode = node->enclosingLinkEventParentOrSelf()) { + KURL href; + if (linkNode->isLink() && linkNode->hasAttributes()) { + if (Attribute* attribute = linkNode->attributes()->getAttributeItem(HTMLNames::hrefAttr)) + href = linkNode->document()->completeURL(stripLeadingAndTrailingHTMLSpaces(attribute->value())); + } + + String pattern = findPatternStringForUrl(href); + if (!pattern.isEmpty()) + context.setPattern(pattern); + + if (!href.string().isEmpty()) { + context.setUrl(href.string()); + + // Links are non-selectable by default, but selection should be allowed + // providing the page is selectable, use the parent to determine it. + if (linkNode->parentNode() && linkNode->parentNode()->canStartSelection()) + nodeAllowSelectionOverride = true; + } + } + + if (!nodeAllowSelectionOverride && !node->canStartSelection()) + context.resetFlag(ActiveNodeContext::IsSelectable); + + if (node->isHTMLElement()) { + HTMLImageElement* imageElement = 0; + if (node->hasTagName(HTMLNames::imgTag)) + imageElement = static_cast<HTMLImageElement*>(node.get()); + else if (node->hasTagName(HTMLNames::areaTag)) + imageElement = static_cast<HTMLAreaElement*>(node.get())->imageElement(); + if (imageElement && imageElement->renderer()) { + // FIXME: At the mean time, we only show "Save Image" when the image data is available. + if (CachedResource* cachedResource = imageElement->cachedImage()) { + if (cachedResource->isLoaded() && cachedResource->data()) { + String url = stripLeadingAndTrailingHTMLSpaces(imageElement->getAttribute(HTMLNames::srcAttr).string()); + context.setImageSrc(node->document()->completeURL(url).string()); + } + } + String alt = imageElement->altText(); + if (!alt.isNull()) + context.setImageAlt(alt); + } + } + + if (node->isTextNode()) { + Text* curText = static_cast<Text*>(node.get()); + if (!curText->wholeText().isEmpty()) + context.setText(curText->wholeText()); + } + + if (node->isElementNode()) { + Element* element = static_cast<Element*>(node->shadowAncestorNode()); + if (DOMSupport::isTextBasedContentEditableElement(element)) { + context.setFlag(ActiveNodeContext::IsInput); + if (element->hasTagName(HTMLNames::inputTag)) + context.setFlag(ActiveNodeContext::IsSingleLine); + if (DOMSupport::isPasswordElement(element)) + context.setFlag(ActiveNodeContext::IsPassword); + + String elementText(DOMSupport::inputElementText(element)); + if (!elementText.stripWhiteSpace().isEmpty()) + context.setText(elementText); + } + } + + if (node->isFocusable()) + context.setFlag(ActiveNodeContext::IsFocusable); + + return context; +} + +void WebPagePrivate::updateCursor() +{ + int buttonMask = 0; + if (m_lastMouseEvent.button() == LeftButton) + buttonMask = Platform::MouseEvent::ScreenLeftMouseButton; + else if (m_lastMouseEvent.button() == MiddleButton) + buttonMask = Platform::MouseEvent::ScreenMiddleMouseButton; + else if (m_lastMouseEvent.button() == RightButton) + buttonMask = Platform::MouseEvent::ScreenRightMouseButton; + + Platform::MouseEvent event(buttonMask, buttonMask, mapToTransformed(m_lastMouseEvent.pos()), mapToTransformed(m_lastMouseEvent.globalPos()), 0, 0); + m_webPage->mouseEvent(event); +} + +IntSize WebPagePrivate::fixedLayoutSize(bool snapToIncrement) const +{ + if (hasVirtualViewport()) + return IntSize(m_virtualViewportWidth, m_virtualViewportHeight); + + const int defaultLayoutWidth = m_defaultLayoutSize.width(); + const int defaultLayoutHeight = m_defaultLayoutSize.height(); + + int minWidth = defaultLayoutWidth; + int maxWidth = defaultMaxLayoutSize().width(); + int maxHeight = defaultMaxLayoutSize().height(); + + // If the load state is none then we haven't actually got anything yet, but we need to layout + // the entire page so that the user sees the entire page (unrendered) instead of just part of it. + if (m_loadState == None) + return IntSize(defaultLayoutWidth, defaultLayoutHeight); + + if (m_viewMode == FixedDesktop) { + int width = maxWidth; + // if the defaultLayoutHeight is at minimum, it probably was set as 0 + // and clamped, meaning it's effectively not set. (Even if it happened + // to be set exactly to the minimum, it's too small to be useful.) So + // ignore it. + int height; + if (defaultLayoutHeight <= minimumLayoutSize.height()) + height = maxHeight; + else + height = ceilf(static_cast<float>(width) / static_cast<float>(defaultLayoutWidth) * static_cast<float>(defaultLayoutHeight)); + return IntSize(width, height); + } + + if (m_viewMode == Desktop) { + // If we detect an overflow larger than the contents size then use that instead since + // it'll still be clamped by the maxWidth below... + int width = std::max(absoluteVisibleOverflowSize().width(), contentsSize().width()); + + if (snapToIncrement) { + // Snap to increments of defaultLayoutWidth / 2.0. + float factor = static_cast<float>(width) / (defaultLayoutWidth / 2.0); + factor = ceilf(factor); + width = (defaultLayoutWidth / 2.0) * factor; + } + + if (width < minWidth) + width = minWidth; + if (width > maxWidth) + width = maxWidth; + int height = ceilf(static_cast<float>(width) / static_cast<float>(defaultLayoutWidth) * static_cast<float>(defaultLayoutHeight)); + return IntSize(width, height); + } + + if (m_webSettings->isZoomToFitOnLoad()) { + // We need to clamp the layout width to the minimum of the layout + // width or the content width. This is important under rotation for mobile + // websites. We want the page to remain layouted at the same width which + // it was loaded with, and instead change the zoom level to fit to screen. + // The height is welcome to adapt to the height used in the new orientation, + // otherwise we will get a grey bar below the web page. + if (m_mainFrame->view() && !contentsSize().isEmpty()) + minWidth = contentsSize().width(); + else { + // If there is no contents width, use the minimum of screen width + // and layout width to shape the first layout to a contents width + // that we could reasonably zoom to fit, in a manner that takes + // orientation into account and still respects a small default + // layout width. +#if ENABLE(ORIENTATION_EVENTS) + minWidth = m_mainFrame->orientation() % 180 + ? Platform::Graphics::Screen::height() + : Platform::Graphics::Screen::width(); +#else + minWidth = Platform::Graphics::Screen::width(); +#endif + } + } + + return IntSize(std::min(minWidth, defaultLayoutWidth), defaultLayoutHeight); +} + +BackingStoreClient* WebPagePrivate::backingStoreClientForFrame(const Frame* frame) const +{ + ASSERT(frame); + BackingStoreClient* backingStoreClient = 0; + if (m_backingStoreClientForFrameMap.contains(frame)) + backingStoreClient = m_backingStoreClientForFrameMap.get(frame); + return backingStoreClient; +} + +void WebPagePrivate::addBackingStoreClientForFrame(const Frame* frame, BackingStoreClient* client) +{ + ASSERT(frame); + ASSERT(client); + m_backingStoreClientForFrameMap.add(frame, client); +} + +void WebPagePrivate::removeBackingStoreClientForFrame(const Frame* frame) +{ + ASSERT(frame); + if (m_backingStoreClientForFrameMap.contains(frame)) + m_backingStoreClientForFrameMap.remove(frame); +} + + +void WebPagePrivate::clearDocumentData(const Document* documentGoingAway) +{ + ASSERT(documentGoingAway); + if (m_currentContextNode && m_currentContextNode->document() == documentGoingAway) + m_currentContextNode = 0; + + if (m_currentPinchZoomNode && m_currentPinchZoomNode->document() == documentGoingAway) + m_currentPinchZoomNode = 0; + + if (m_currentBlockZoomAdjustedNode && m_currentBlockZoomAdjustedNode->document() == documentGoingAway) + m_currentBlockZoomAdjustedNode = 0; + + if (m_inRegionScrollStartingNode && m_inRegionScrollStartingNode->document() == documentGoingAway) + m_inRegionScrollStartingNode = 0; + + Node* nodeUnderFatFinger = m_touchEventHandler->lastFatFingersResult().node(); + if (nodeUnderFatFinger && nodeUnderFatFinger->document() == documentGoingAway) + m_touchEventHandler->resetLastFatFingersResult(); + + // NOTE: m_fullscreenVideoNode, m_fullScreenPluginView and m_pluginViews + // are cleared in other methods already. +} + +typedef bool (*PredicateFunction)(RenderLayer*); +static bool isPositionedContainer(RenderLayer* layer) +{ + RenderObject* o = layer->renderer(); + return o->isRenderView() || o->isPositioned() || o->isRelPositioned() || layer->hasTransform(); +} + +static bool isNonRenderViewFixedPositionedContainer(RenderLayer* layer) +{ + RenderObject* o = layer->renderer(); + if (o->isRenderView()) + return false; + + return o->isPositioned() && o->style()->position() == FixedPosition; +} + +static bool isFixedPositionedContainer(RenderLayer* layer) +{ + RenderObject* o = layer->renderer(); + return o->isRenderView() || (o->isPositioned() && o->style()->position() == FixedPosition); +} + +static RenderLayer* findAncestorOrSelfNotMatching(PredicateFunction predicate, RenderLayer* layer) +{ + RenderLayer* curr = layer; + while (curr && !predicate(curr)) + curr = curr->parent(); + + return curr; +} + +RenderLayer* WebPagePrivate::enclosingFixedPositionedAncestorOrSelfIfFixedPositioned(RenderLayer* layer) +{ + return findAncestorOrSelfNotMatching(&isFixedPositionedContainer, layer); +} + +RenderLayer* WebPagePrivate::enclosingPositionedAncestorOrSelfIfPositioned(RenderLayer* layer) +{ + return findAncestorOrSelfNotMatching(&isPositionedContainer, layer); +} + +static inline Frame* frameForNode(Node* node) +{ + Node* origNode = node; + for (; node; node = node->parentNode()) { + if (RenderObject* renderer = node->renderer()) { + if (renderer->isRenderView()) { + if (FrameView* view = toRenderView(renderer)->frameView()) { + if (Frame* frame = view->frame()) + return frame; + } + } + if (renderer->isWidget()) { + Widget* widget = toRenderWidget(renderer)->widget(); + if (widget && widget->isFrameView()) { + if (Frame* frame = static_cast<FrameView*>(widget)->frame()) + return frame; + } + } + } + } + + for (node = origNode; node; node = node->parentNode()) { + if (Document* doc = node->document()) { + if (Frame* frame = doc->frame()) + return frame; + } + } + + return 0; +} + +static IntRect getNodeWindowRect(Node* node) +{ + if (Frame* frame = frameForNode(node)) { + if (FrameView* view = frame->view()) + return view->contentsToWindow(node->getRect()); + } + ASSERT_NOT_REACHED(); + return IntRect(); +} + +IntRect WebPagePrivate::getRecursiveVisibleWindowRect(ScrollView* view, bool noClipOfMainFrame) +{ + ASSERT(m_mainFrame); + + // Don't call this function asking to not clip the main frame providing only + // the main frame. All that can be returned is the content rect which + // isn't what this function is for. + if (noClipOfMainFrame && view == m_mainFrame->view()) { + ASSERT_NOT_REACHED(); + return IntRect(IntPoint::zero(), view->contentsSize()); + } + + IntRect visibleWindowRect(view->contentsToWindow(view->visibleContentRect(false))); + if (view->parent() && !(noClipOfMainFrame && view->parent() == m_mainFrame->view())) { + // Intersect with parent visible rect. + visibleWindowRect.intersect(getRecursiveVisibleWindowRect(view->parent(), noClipOfMainFrame)); + } + return visibleWindowRect; +} + +void WebPage::assignFocus(Platform::FocusDirection direction) +{ + d->assignFocus(direction); +} + +void WebPagePrivate::assignFocus(Platform::FocusDirection direction) +{ + ASSERT((int) Platform::FocusDirectionNone == (int) FocusDirectionNone); + ASSERT((int) Platform::FocusDirectionForward == (int) FocusDirectionForward); + ASSERT((int) Platform::FocusDirectionBackward == (int) FocusDirectionBackward); + + // First we clear the focus, since we want to focus either initial or the last + // focusable element in the webpage (according to the TABINDEX), or simply clear + // the focus. + clearFocusNode(); + + switch (direction) { + case FocusDirectionForward: + case FocusDirectionBackward: + m_page->focusController()->setInitialFocus((FocusDirection) direction, 0); + break; + case FocusDirectionNone: + break; + default: + ASSERT_NOT_REACHED(); + } +} + +Platform::IntRect WebPagePrivate::focusNodeRect() +{ + Frame* frame = focusedOrMainFrame(); + if (!frame) + return Platform::IntRect(); + + Document* doc = frame->document(); + FrameView* view = frame->view(); + if (!doc || !view || view->needsLayout()) + return Platform::IntRect(); + + IntRect focusRect = rectForNode(doc->focusedNode()); + focusRect = adjustRectOffsetForFrameOffset(focusRect, doc->focusedNode()); + focusRect = mapToTransformed(focusRect); + clipToTransformedContentsRect(focusRect); + return focusRect; +} + +PassRefPtr<Node> WebPagePrivate::contextNode(TargetDetectionStrategy strategy) +{ + EventHandler* eventHandler = focusedOrMainFrame()->eventHandler(); + const FatFingersResult lastFatFingersResult = m_touchEventHandler->lastFatFingersResult(); + bool isTouching = lastFatFingersResult.isValid() && strategy == RectBased; + + // Unpress the mouse button always. + if (eventHandler->mousePressed()) + eventHandler->setMousePressed(false); + + // Check if we're using LinkToLink and the user is not touching the screen. + if (m_webSettings->doesGetFocusNodeContext() && !isTouching) { + RefPtr<Node> node; + node = m_page->focusController()->focusedOrMainFrame()->document()->focusedNode(); + if (node) { + IntRect visibleRect = IntRect(IntPoint(), actualVisibleSize()); + if (!visibleRect.intersects(getNodeWindowRect(node.get()))) + return 0; + } + return node.release(); + } + + // Check for text input. + if (isTouching && lastFatFingersResult.isTextInput()) + return lastFatFingersResult.node(FatFingersResult::ShadowContentNotAllowed); + + IntPoint contentPos; + if (isTouching) + contentPos = lastFatFingersResult.adjustedPosition(); + else + contentPos = mapFromViewportToContents(m_lastMouseEvent.pos()); + + if (strategy == RectBased) { + FatFingersResult result = FatFingers(this, lastFatFingersResult.adjustedPosition(), FatFingers::Text).findBestPoint(); + return result.node(FatFingersResult::ShadowContentNotAllowed); + } + + HitTestResult result = eventHandler->hitTestResultAtPoint(contentPos, false /*allowShadowContent*/); + return result.innerNode(); +} + +static inline int distanceBetweenPoints(IntPoint p1, IntPoint p2) +{ + // Change int to double, because (dy * dy) can cause int overflow in reality, e.g, (-46709 * -46709). + double dx = static_cast<double>(p1.x() - p2.x()); + double dy = static_cast<double>(p1.y() - p2.y()); + return sqrt((dx * dx) + (dy * dy)); +} + +Node* WebPagePrivate::bestNodeForZoomUnderPoint(const IntPoint& point) +{ + IntPoint pt = mapFromTransformed(point); + IntRect clickRect(pt.x() - blockClickRadius, pt.y() - blockClickRadius, 2 * blockClickRadius, 2 * blockClickRadius); + Node* originalNode = nodeForZoomUnderPoint(point); + if (!originalNode) + return 0; + Node* node = bestChildNodeForClickRect(originalNode, clickRect); + return node ? adjustedBlockZoomNodeForZoomLimits(node) : adjustedBlockZoomNodeForZoomLimits(originalNode); +} + +Node* WebPagePrivate::bestChildNodeForClickRect(Node* parentNode, const IntRect& clickRect) +{ + if (!parentNode) + return 0; + + int bestDistance = std::numeric_limits<int>::max(); + + Node* node = parentNode->firstChild(); + Node* bestNode = 0; + for (; node; node = node->nextSibling()) { + IntRect rect = rectForNode(node); + if (!clickRect.intersects(rect)) + continue; + + int distance = distanceBetweenPoints(rect.center(), clickRect.center()); + Node* bestChildNode = bestChildNodeForClickRect(node, clickRect); + if (bestChildNode) { + IntRect bestChildRect = rectForNode(bestChildNode); + int bestChildDistance = distanceBetweenPoints(bestChildRect.center(), clickRect.center()); + if (bestChildDistance < distance && bestChildDistance < bestDistance) { + bestNode = bestChildNode; + bestDistance = bestChildDistance; + } else { + if (distance < bestDistance) { + bestNode = node; + bestDistance = distance; + } + } + } else { + if (distance < bestDistance) { + bestNode = node; + bestDistance = distance; + } + } + } + + return bestNode; +} + +double WebPagePrivate::maxBlockZoomScale() const +{ + return std::min(maximumBlockZoomScale, maximumScale()); +} + +Node* WebPagePrivate::nodeForZoomUnderPoint(const IntPoint& point) +{ + if (!m_mainFrame) + return 0; + + HitTestResult result = m_mainFrame->eventHandler()->hitTestResultAtPoint(mapFromTransformed(point), false); + + Node* node = result.innerNonSharedNode(); + + if (!node) + return 0; + + RenderObject* renderer = node->renderer(); + while (!renderer) { + node = node->parentNode(); + renderer = node->renderer(); + } + + return node; +} + +Node* WebPagePrivate::adjustedBlockZoomNodeForZoomLimits(Node* node) +{ + Node* initialNode = node; + RenderObject* renderer = node->renderer(); + bool acceptableNodeSize = newScaleForBlockZoomRect(rectForNode(node), 1.0, 0) < maxBlockZoomScale(); + + while (!renderer || !acceptableNodeSize) { + node = node->parentNode(); + + if (!node) + return initialNode; + + renderer = node->renderer(); + acceptableNodeSize = newScaleForBlockZoomRect(rectForNode(node), 1.0, 0) < maxBlockZoomScale(); + } + + return node; +} + +bool WebPagePrivate::compareNodesForBlockZoom(Node* n1, Node* n2) +{ + if (!n1 || !n2) + return false; + + return (n2 == n1) || n2->isDescendantOf(n1); +} + +double WebPagePrivate::newScaleForBlockZoomRect(const IntRect& rect, double oldScale, double margin) +{ + if (rect.isEmpty()) + return std::numeric_limits<double>::max(); + + ASSERT(rect.width() + margin); + + double newScale = oldScale * static_cast<double>(transformedActualVisibleSize().width()) / (rect.width() + margin); + + return newScale; +} + +IntRect WebPagePrivate::rectForNode(Node* node) +{ + if (!node) + return IntRect(); + + RenderObject* renderer = node->renderer(); + + if (!renderer) + return IntRect(); + + // Return rect in un-transformed content coordinates. + IntRect blockRect; + + // FIXME: Ensure this works with iframes. + if (m_webPage->settings()->textReflowMode() == WebSettings::TextReflowEnabled && renderer->isText()) { + RenderBlock* renderBlock = renderer->containingBlock(); + int xOffset = 0; + int yOffset = 0; + while (!renderBlock->isRoot()) { + xOffset += renderBlock->x(); + yOffset += renderBlock->y(); + renderBlock = renderBlock->containingBlock(); + } + const RenderText* renderText = toRenderText(renderer); + IntRect linesBox = renderText->linesBoundingBox(); + blockRect = IntRect(xOffset + linesBox.x(), yOffset + linesBox.y(), linesBox.width(), linesBox.height()); + } else + blockRect = renderer->absoluteClippedOverflowRect(); + + if (renderer->isText()) { + RenderBlock* rb = renderer->containingBlock(); + + // Inefficient? Way to find width when floats intersect a block. + int blockWidth = 0; + int lineCount = rb->lineCount(); + for (int i = 0; i < lineCount; i++) + blockWidth = max(blockWidth, rb->availableLogicalWidthForLine(i, false)); + + blockRect.setWidth(blockWidth); + blockRect.setX(blockRect.x() + rb->logicalLeftOffsetForLine(1, false)); + } + + // Strip off padding. + if (renderer->style()->hasPadding()) { + blockRect.setX(blockRect.x() + renderer->style()->paddingLeft().value()); + blockRect.setY(blockRect.y() + renderer->style()->paddingTop().value()); + blockRect.setWidth(blockRect.width() - renderer->style()->paddingRight().value()); + blockRect.setHeight(blockRect.height() - renderer->style()->paddingBottom().value()); + } + + return blockRect; +} + +IntPoint WebPagePrivate::frameOffset(const Frame* frame) const +{ + ASSERT(frame); + + // FIXME: This function can be called when page is being destroyed and JS triggers selection change. + // We could break the call chain at upper levels, but I think it is better to check the frame pointer + // here because the pointer is explicitly cleared in WebPage::destroy(). + if (!mainFrame()) + return IntPoint(); + + // Convert 0,0 in the frame's coordinate system to window coordinates to + // get the frame's global position, and return this position in the main + // frame's coordinates. (So the main frame's coordinates will be 0,0.) + return mainFrame()->view()->windowToContents(frame->view()->contentsToWindow(IntPoint::zero())); +} + +IntRect WebPagePrivate::adjustRectOffsetForFrameOffset(const IntRect& rect, const Node* node) +{ + if (!node) + return rect; + + // Adjust the offset of the rect if it is in an iFrame/frame or set of iFrames/frames. + // FIXME: can we just use frameOffset instead of this big routine? + const Node* tnode = node; + IntRect adjustedRect = rect; + do { + Frame* frame = tnode->document()->frame(); + if (!frame) + continue; + + Node* ownerNode = static_cast<Node*>(frame->ownerElement()); + tnode = ownerNode; + if (ownerNode && (ownerNode->hasTagName(HTMLNames::iframeTag) || ownerNode->hasTagName(HTMLNames::frameTag))) { + IntRect iFrameRect; + do { + iFrameRect = rectForNode(ownerNode); + adjustedRect.move(iFrameRect.x(), iFrameRect.y()); + adjustedRect.intersect(iFrameRect); + ownerNode = ownerNode->parentNode(); + } while (iFrameRect.isEmpty() && ownerNode); + } else + break; + } while (tnode = tnode->parentNode()); + + return adjustedRect; +} + +IntRect WebPagePrivate::blockZoomRectForNode(Node* node) +{ + if (!node || contentsSize().isEmpty()) + return IntRect(); + + Node* tnode = node; + m_currentBlockZoomAdjustedNode = tnode; + + IntRect blockRect = rectForNode(tnode); + IntRect originalRect = blockRect; + + int originalArea = originalRect.width() * originalRect.height(); + int pageArea = contentsSize().width() * contentsSize().height(); + double blockToPageRatio = static_cast<double>(1 - originalArea / pageArea); + double blockExpansionRatio = 5.0 * blockToPageRatio * blockToPageRatio; + + if (!tnode->hasTagName(HTMLNames::imgTag) && !tnode->hasTagName(HTMLNames::inputTag) && !tnode->hasTagName(HTMLNames::textareaTag)) { + while (tnode = tnode->parentNode()) { + ASSERT(tnode); + IntRect tRect = rectForNode(tnode); + int tempBlockArea = tRect.width() * tRect.height(); + // Don't expand the block if it will be too large relative to the content. + if (static_cast<double>(1 - tempBlockArea / pageArea) < minimumExpandingRatio) + break; + if (tRect.isEmpty()) + continue; // No renderer. + if (tempBlockArea < 1.1 * originalArea) + continue; // The size of this parent is very close to the child, no need to go to this parent. + // Don't expand the block if the parent node size is already almost the size of actual visible size. + IntSize actualSize = actualVisibleSize(); + if (static_cast<double>(1 - tRect.width() / actualSize.width()) < minimumExpandingRatio) + break; + if (tempBlockArea < blockExpansionRatio * originalArea) { + blockRect = tRect; + m_currentBlockZoomAdjustedNode = tnode; + } else + break; + } + } + + blockRect = adjustRectOffsetForFrameOffset(blockRect, node); + blockRect = mapToTransformed(blockRect); + clipToTransformedContentsRect(blockRect); + +#if DEBUG_BLOCK_ZOOM + // Re-paint the backingstore to screen to erase other annotations. + m_backingStore->d->resumeScreenAndBackingStoreUpdates(BackingStore::Blit); + + // Render a black square over the calculated block and a gray square over the original block for visual inspection. + originalRect = mapToTransformed(originalRect); + clipToTransformedContentsRect(originalRect); + IntRect renderRect = mapFromTransformedContentsToTransformedViewport(blockRect); + IntRect originalRenderRect = mapFromTransformedContentsToTransformedViewport(originalRect); + IntSize viewportSize = transformedViewportSize(); + renderRect.intersect(IntRect(0, 0, viewportSize.width(), viewportSize.height())); + originalRenderRect.intersect(IntRect(0, 0, viewportSize.width(), viewportSize.height())); + m_backingStore->d->clearWindow(renderRect, 0, 0, 0); + m_backingStore->d->clearWindow(originalRenderRect, 120, 120, 120); + m_backingStore->d->invalidateWindow(renderRect); +#endif + + return blockRect; +} + +void WebPage::blockZoomAnimationFinished() +{ + d->zoomBlock(); +} + +// This function should not be called directly. +// It is called after the animation ends (see above). +void WebPagePrivate::zoomBlock() +{ + if (!m_mainFrame) + return; + + IntPoint anchor(roundUntransformedPoint(mapFromTransformedFloatPoint(m_finalBlockPoint))); + bool willUseTextReflow = false; + +#if ENABLE(VIEWPORT_REFLOW) + willUseTextReflow = m_webPage->settings()->textReflowMode() != WebSettings::TextReflowDisabled; + toggleTextReflowIfEnabledForBlockZoomOnly(m_shouldReflowBlock); + setNeedsLayout(); +#endif + + TransformationMatrix zoom; + zoom.scale(m_blockZoomFinalScale); + *m_transformationMatrix = zoom; + m_client->resetBitmapZoomScale(m_blockZoomFinalScale); + m_backingStore->d->suspendScreenAndBackingStoreUpdates(); + updateViewportSize(); + +#if ENABLE(VIEWPORT_REFLOW) + requestLayoutIfNeeded(); + if (willUseTextReflow && m_shouldReflowBlock) { + IntRect reflowedRect = rectForNode(m_currentBlockZoomAdjustedNode.get()); + reflowedRect = adjustRectOffsetForFrameOffset(reflowedRect, m_currentBlockZoomAdjustedNode.get()); + reflowedRect.move(roundTransformedPoint(m_finalBlockPointReflowOffset).x(), roundTransformedPoint(m_finalBlockPointReflowOffset).y()); + RenderObject* renderer = m_currentBlockZoomAdjustedNode->renderer(); + IntPoint topLeftPoint(reflowedRect.location()); + if (renderer && renderer->isText()) { + ETextAlign textAlign = renderer->style()->textAlign(); + IntPoint textAnchor; + switch (textAlign) { + case CENTER: + case WEBKIT_CENTER: + textAnchor = IntPoint(reflowedRect.x() + (reflowedRect.width() - actualVisibleSize().width()) / 2, topLeftPoint.y()); + break; + case LEFT: + case WEBKIT_LEFT: + textAnchor = topLeftPoint; + break; + case RIGHT: + case WEBKIT_RIGHT: + textAnchor = IntPoint(reflowedRect.x() + reflowedRect.width() - actualVisibleSize().width(), topLeftPoint.y()); + break; + case TAAUTO: + case JUSTIFY: + default: + if (renderer->style()->isLeftToRightDirection()) + textAnchor = topLeftPoint; + else + textAnchor = IntPoint(reflowedRect.x() + reflowedRect.width() - actualVisibleSize().width(), topLeftPoint.y()); + break; + } + setScrollPosition(textAnchor); + } else { + renderer->style()->isLeftToRightDirection() + ? setScrollPosition(topLeftPoint) + : setScrollPosition(IntPoint(reflowedRect.x() + reflowedRect.width() - actualVisibleSize().width(), topLeftPoint.y())); + } + } else if (willUseTextReflow) { + IntRect finalRect = rectForNode(m_currentBlockZoomAdjustedNode.get()); + finalRect = adjustRectOffsetForFrameOffset(finalRect, m_currentBlockZoomAdjustedNode.get()); + setScrollPosition(IntPoint(0, finalRect.y() + m_finalBlockPointReflowOffset.y())); + resetBlockZoom(); + } +#endif + if (!willUseTextReflow) { + setScrollPosition(anchor); + if (!m_shouldReflowBlock) + resetBlockZoom(); + } + + notifyTransformChanged(); + m_backingStore->d->clearWindow(); + m_backingStore->d->resumeScreenAndBackingStoreUpdates(BackingStore::RenderAndBlit); + m_client->zoomChanged(m_webPage->isMinZoomed(), m_webPage->isMaxZoomed(), !shouldZoomOnEscape(), currentScale()); +} + + +void WebPagePrivate::resetBlockZoom() +{ + m_currentBlockZoomNode = 0; + m_currentBlockZoomAdjustedNode = 0; + m_shouldReflowBlock = false; +} + +WebPage::WebPage(WebPageClient* client, const WebString& pageGroupName, const Platform::IntRect& rect) +{ + globalInitialize(); + d = new WebPagePrivate(this, client, rect); + d->init(pageGroupName); +} + +void WebPage::destroyWebPageCompositor() +{ +#if USE(ACCELERATED_COMPOSITING) + // Destroy the layer renderer in a sync command before we destroy the backing store, + // to flush any pending compositing messages on the compositing thread. + // The backing store is indirectly deleted by the 'detachFromParent' call below. + d->syncDestroyCompositorOnCompositingThread(); +#endif +} + +void WebPage::destroy() +{ + // TODO: need to verify if this call needs to be made before calling + // WebPage::destroyWebPageCompositor() + d->m_backingStore->d->suspendScreenAndBackingStoreUpdates(); + + // Close the backforward list and release the cached pages. + d->m_page->backForward()->close(); + pageCache()->releaseAutoreleasedPagesNow(); + + FrameLoader* loader = d->m_mainFrame->loader(); + + // Remove main frame's backing store client from the map + // to prevent FrameLoaderClientBlackyBerry::detachFromParent2(), + // which is called by loader->detachFromParent(), deleting it. + // We will delete it in ~WebPagePrivate(). + // Reason: loader->detachFromParent() may ping back to backing store + // indirectly through ChromeClientBlackBerry::invalidateContentsAndWindow(). + // see RIM PR #93256. + d->removeBackingStoreClientForFrame(d->m_mainFrame); + + // Set m_mainFrame to 0 to avoid calls back in to the backingstore during webpage deletion. + d->m_mainFrame = 0; + if (loader) + loader->detachFromParent(); + + delete this; +} + +WebPage::~WebPage() +{ + delete d; + d = 0; +} + +WebPageClient* WebPage::client() const +{ + return d->m_client; +} + +void WebPage::load(const char* url, const char* networkToken, bool isInitial) +{ + d->load(url, networkToken, "GET", Platform::NetworkRequest::UseProtocolCachePolicy, 0, 0, 0, 0, isInitial, false); +} + +void WebPage::loadExtended(const char* url, const char* networkToken, const char* method, Platform::NetworkRequest::CachePolicy cachePolicy, const char* data, size_t dataLength, const char* const* headers, size_t headersLength, bool mustHandleInternally) +{ + d->load(url, networkToken, method, cachePolicy, data, dataLength, headers, headersLength, false, mustHandleInternally, false, ""); +} + +void WebPage::loadFile(const char* path, const char* overrideContentType) +{ + std::string fileUrl(path); + if (!fileUrl.find("/")) + fileUrl.insert(0, "file://"); + else if (fileUrl.find("file:///")) + return; + + d->load(fileUrl.c_str(), 0, "GET", Platform::NetworkRequest::UseProtocolCachePolicy, 0, 0, 0, 0, false, false, false, overrideContentType); +} + +void WebPage::loadString(const char* string, const char* baseURL, const char* mimeType, const char* failingURL) +{ + d->loadString(string, baseURL, mimeType, failingURL); +} + +void WebPage::download(const Platform::NetworkRequest& request) +{ + d->load(request.getUrlRef().c_str(), 0, "GET", Platform::NetworkRequest::UseProtocolCachePolicy, 0, 0, 0, 0, false, false, true, ""); +} + +bool WebPage::executeJavaScript(const char* script, JavaScriptDataType& returnType, WebString& returnValue) +{ + return d->executeJavaScript(script, returnType, returnValue); +} + +bool WebPage::executeJavaScriptInIsolatedWorld(const std::wstring& script, JavaScriptDataType& returnType, WebString& returnValue) +{ + // On our platform wchar_t is unsigned int and UChar is unsigned short + // so we have to convert using ICU conversion function + int lengthCopied = 0; + UErrorCode error = U_ZERO_ERROR; + const int length = script.length() + 1 /*null termination char*/; + UChar data[length]; + + // FIXME: PR 138162 is giving U_INVALID_CHAR_FOUND error. + u_strFromUTF32(data, length, &lengthCopied, reinterpret_cast<const UChar32*>(script.c_str()), script.length(), &error); + BLACKBERRY_ASSERT(error == U_ZERO_ERROR); + if (error != U_ZERO_ERROR) { + Platform::logAlways(Platform::LogLevelCritical, "WebPage::executeJavaScriptInIsolatedWorld failed to convert UTF16 to JavaScript!"); + return false; + } + String str = String(data, lengthCopied); + ScriptSourceCode sourceCode(str, KURL()); + return d->executeJavaScriptInIsolatedWorld(sourceCode, returnType, returnValue); +} + +bool WebPage::executeJavaScriptInIsolatedWorld(const char* script, JavaScriptDataType& returnType, WebString& returnValue) +{ + ScriptSourceCode sourceCode(String::fromUTF8(script), KURL()); + return d->executeJavaScriptInIsolatedWorld(sourceCode, returnType, returnValue); +} + +void WebPage::stopLoading() +{ + d->stopCurrentLoad(); +} + +void WebPage::prepareToDestroy() +{ + d->prepareToDestroy(); +} + +int WebPage::backForwardListLength() const +{ + return d->m_page->getHistoryLength(); +} + +bool WebPage::canGoBackOrForward(int delta) const +{ + return d->m_page->canGoBackOrForward(delta); +} + +bool WebPage::goBackOrForward(int delta) +{ + if (d->m_page->canGoBackOrForward(delta)) { + d->m_page->goBackOrForward(delta); + return true; + } + return false; +} + +void WebPage::goToBackForwardEntry(BackForwardId id) +{ + HistoryItem* item = historyItemFromBackForwardId(id); + ASSERT(item); + d->m_page->goToItem(item, FrameLoadTypeIndexedBackForward); +} + +void WebPage::reload() +{ + d->m_mainFrame->loader()->reload(/* bypassCache */ true); +} + +void WebPage::reloadFromCache() +{ + d->m_mainFrame->loader()->reload(/* bypassCache */ false); +} + +WebSettings* WebPage::settings() const +{ + return d->m_webSettings; +} + +bool WebPage::isVisible() const +{ + return d->m_visible; +} + +void WebPage::setVisible(bool visible) +{ + if (d->m_visible == visible) + return; + + d->m_visible = visible; + + if (!visible) { + d->suspendBackingStore(); + + // Remove this WebPage from the visible pages list. + size_t foundIndex = visibleWebPages()->find(this); + if (foundIndex != WTF::notFound) + visibleWebPages()->remove(foundIndex); + + // Return the backing store to the last visible WebPage. + if (BackingStorePrivate::currentBackingStoreOwner() == this && !visibleWebPages()->isEmpty()) + visibleWebPages()->last()->d->resumeBackingStore(); + +#if USE(ACCELERATED_COMPOSITING) + // Root layer commit is not necessary for invisible tabs. + // And release layer resources can reduce memory consumption. + d->suspendRootLayerCommit(); +#endif + return; + } + +#if USE(ACCELERATED_COMPOSITING) + d->resumeRootLayerCommit(); +#endif + + // Push this WebPage to the top of the visible pages list. + if (!visibleWebPages()->isEmpty() && visibleWebPages()->last() != this) { + size_t foundIndex = visibleWebPages()->find(this); + if (foundIndex != WTF::notFound) + visibleWebPages()->remove(foundIndex); + } + visibleWebPages()->append(this); + + if (BackingStorePrivate::currentBackingStoreOwner() + && BackingStorePrivate::currentBackingStoreOwner() != this) + BackingStorePrivate::currentBackingStoreOwner()->d->suspendBackingStore(); + + // resumeBackingStore will set the current owner to this webpage. + // If we set the owner prematurely, then the tiles will not be reset. + d->resumeBackingStore(); +} + +void WebPagePrivate::selectionChanged(Frame* frame) +{ + m_inputHandler->selectionChanged(); + + // FIXME: This is a hack! + // To ensure the selection being changed has its frame 'focused', lets + // set it as focused ourselves (PR #104724). + m_page->focusController()->setFocusedFrame(frame); +} + +void WebPagePrivate::updateDelegatedOverlays(bool dispatched) +{ + // Track a dispatched message, we don't want to flood the webkit thread. + // There can be as many as one more message enqued as needed but never less. + if (dispatched) + m_updateDelegatedOverlaysDispatched = false; + else if (m_updateDelegatedOverlaysDispatched) { + // Early return if there is message already pending on the webkit thread. + return; + } + + if (Platform::webKitThreadMessageClient()->isCurrentThread()) { + // Must be called on the WebKit thread. + if (m_selectionHandler->isSelectionActive()) + m_selectionHandler->selectionPositionChanged(true /* visualChangeOnly */); + + } else if (m_selectionHandler->isSelectionActive()) { + // Don't bother dispatching to webkit thread if selection and tap highlight are not active. + m_updateDelegatedOverlaysDispatched = true; + Platform::webKitThreadMessageClient()->dispatchMessage(Platform::createMethodCallMessage(&WebPagePrivate::updateDelegatedOverlays, this, true /*dispatched*/)); + } +} + +void WebPage::setCaretHighlightStyle(Platform::CaretHighlightStyle style) +{ +} + +bool WebPage::setBatchEditingActive(bool active) +{ + return d->m_inputHandler->setBatchEditingActive(active); +} + +bool WebPage::setInputSelection(unsigned start, unsigned end) +{ + return d->m_inputHandler->setSelection(start, end); +} + +int WebPage::inputCaretPosition() const +{ + return d->m_inputHandler->caretPosition(); +} + +void WebPage::popupListClosed(int size, bool* selecteds) +{ + d->m_inputHandler->setPopupListIndexes(size, selecteds); +} + +void WebPage::popupListClosed(int index) +{ + d->m_inputHandler->setPopupListIndex(index); +} + +void WebPage::setDateTimeInput(const WebString& value) +{ + d->m_inputHandler->setInputValue(String(value.impl())); +} + +void WebPage::setColorInput(const WebString& value) +{ + d->m_inputHandler->setInputValue(String(value.impl())); +} + +ActiveNodeContext WebPage::activeNodeContext(TargetDetectionStrategy strategy) const +{ + return d->activeNodeContext(strategy); +} + +void WebPage::setVirtualViewportSize(int width, int height) +{ + d->m_virtualViewportWidth = width; + d->m_virtualViewportHeight = height; +} + +void WebPage::resetVirtualViewportOnCommitted(bool reset) +{ + d->m_resetVirtualViewportOnCommitted = reset; +} + +IntSize WebPagePrivate::recomputeVirtualViewportFromViewportArguments() +{ + static ViewportArguments defaultViewportArguments; + if (m_viewportArguments == defaultViewportArguments) + return IntSize(); + + int desktopWidth = defaultMaxLayoutSize().width(); + int deviceWidth = Platform::Graphics::Screen::width(); + int deviceHeight = Platform::Graphics::Screen::height(); + FloatSize currentPPI = Platform::Graphics::Screen::pixelsPerInch(-1); + int deviceDPI = int(roundf((currentPPI.width() + currentPPI.height()) / 2)); + if (m_viewportArguments.targetDensityDpi == ViewportArguments::ValueAuto) { + // Auto means 160dpi if we leave it alone. This looks terrible for pages wanting 1:1. + // FIXME: This is insufficient for devices with high dpi, as they will render content unreadably small. + m_viewportArguments.targetDensityDpi = deviceDPI; + } + + ViewportAttributes result = computeViewportAttributes(m_viewportArguments, desktopWidth, deviceWidth, deviceHeight, deviceDPI, m_defaultLayoutSize); + return IntSize(result.layoutSize.width(), result.layoutSize.height()); +} + +#if ENABLE(EVENT_MODE_METATAGS) +void WebPagePrivate::didReceiveCursorEventMode(CursorEventMode mode) +{ + if (mode != m_cursorEventMode) + m_client->cursorEventModeChanged(toPlatformCursorEventMode(mode)); + m_cursorEventMode = mode; +} + +void WebPagePrivate::didReceiveTouchEventMode(TouchEventMode mode) +{ + if (mode != m_touchEventMode) + m_client->touchEventModeChanged(toPlatformTouchEventMode(mode)); + m_touchEventMode = mode; +} +#endif + +void WebPagePrivate::dispatchViewportPropertiesDidChange(const ViewportArguments& arguments) +{ + static ViewportArguments defaultViewportArguments; + if (arguments == defaultViewportArguments) + return; + + m_viewportArguments = arguments; + + // 0 width or height in viewport arguments makes no sense, and results in a very large initial scale. + // In real world, a 0 width or height is usually caused by a syntax error in "content" field of viewport + // meta tag, for example, using semicolon instead of comma as separator ("width=device-width; initial-scale=1.0"). + // We don't have a plan to tolerate the semicolon separator, but we can avoid applying 0 width/height. + // I default it to ValueDeviceWidth rather than ValueAuto because in more cases the web site wants "device-width" + // when they specify the viewport width. + if (!m_viewportArguments.width) + m_viewportArguments.width = ViewportArguments::ValueDeviceWidth; + if (!m_viewportArguments.height) + m_viewportArguments.height = ViewportArguments::ValueDeviceHeight; + + setUserScalable(arguments.userScalable == ViewportArguments::ValueAuto ? true : arguments.userScalable); + if (arguments.initialScale > 0) + setInitialScale(arguments.initialScale); + if (arguments.minimumScale > 0) + setMinimumScale(arguments.minimumScale); + if (arguments.maximumScale > 0) + setMaximumScale(arguments.maximumScale); + + IntSize virtualViewport = recomputeVirtualViewportFromViewportArguments(); + m_webPage->setVirtualViewportSize(virtualViewport.width(), virtualViewport.height()); + + if (loadState() == WebKit::WebPagePrivate::Committed) + zoomToInitialScaleOnLoad(); +} + +void WebPagePrivate::onInputLocaleChanged(bool isRTL) +{ + if (isRTL != m_webSettings->isWritingDirectionRTL()) { + m_webSettings->setWritingDirectionRTL(isRTL); + m_inputHandler->handleInputLocaleChanged(isRTL); + } +} + +void WebPage::setScreenOrientation(int orientation) +{ + d->m_pendingOrientation = orientation; +} + +void WebPage::applyPendingOrientationIfNeeded() +{ + if (d->m_pendingOrientation != -1) + d->setScreenOrientation(d->m_pendingOrientation); +} + +void WebPagePrivate::suspendBackingStore() +{ +#if USE(ACCELERATED_COMPOSITING) + resetCompositingSurface(); +#endif +} + +void WebPagePrivate::resumeBackingStore() +{ + ASSERT(m_webPage->isVisible()); + +#if USE(ACCELERATED_COMPOSITING) + setNeedsOneShotDrawingSynchronization(); +#endif + + bool directRendering = m_backingStore->d->shouldDirectRenderingToWindow(); + if (!m_backingStore->d->isActive() + || shouldResetTilesWhenShown() + || directRendering) { + // We need to reset all tiles so that we do not show any tiles whose content may + // have been replaced by another WebPage instance (i.e. another tab). + BackingStorePrivate::setCurrentBackingStoreOwner(m_webPage); + m_backingStore->d->orientationChanged(); // Updates tile geometry and creates visible tile buffer. + m_backingStore->d->resetTiles(true /* resetBackground */); + m_backingStore->d->updateTiles(false /* updateVisible */, false /* immediate */); + // This value may have changed, so we need to update it. + directRendering = m_backingStore->d->shouldDirectRenderingToWindow(); + if (m_backingStore->d->renderVisibleContents() && !m_backingStore->d->isSuspended() && !directRendering) + m_backingStore->d->blitVisibleContents(); + } else { + // Rendering was disabled while we were hidden, so we need to update all tiles. + m_backingStore->d->updateTiles(true /* updateVisible */, false /* immediate */); + } + + setShouldResetTilesWhenShown(false); +} + +void WebPagePrivate::setScreenOrientation(int orientation) +{ + FOR_EACH_PLUGINVIEW(m_pluginViews) + (*it)->handleOrientationEvent(orientation); + + m_pendingOrientation = -1; + +#if ENABLE(ORIENTATION_EVENTS) + if (m_mainFrame->orientation() == orientation) + return; + for (RefPtr<Frame> frame = m_mainFrame; frame; frame = frame->tree()->traverseNext()) + frame->sendOrientationChangeEvent(orientation); +#endif +} + +Platform::IntSize WebPage::viewportSize() const +{ + return d->transformedActualVisibleSize(); +} + +void WebPage::setViewportSize(const Platform::IntSize& viewportSize, bool ensureFocusElementVisible) +{ + d->setViewportSize(viewportSize, ensureFocusElementVisible); +} + +void WebPagePrivate::screenRotated() +{ + // This call will cause the client to reallocate the window buffer to new size, + // which needs to be serialized with usage of the window buffer. Accomplish + // this by sending a sync message to the compositing thread. All other usage of + // the window buffer happens on the compositing thread. + if (!Platform::userInterfaceThreadMessageClient()->isCurrentThread()) { + Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage( + Platform::createMethodCallMessage(&WebPagePrivate::screenRotated, this)); + return; + } + + SurfacePool::globalSurfacePool()->notifyScreenRotated(); + m_client->notifyScreenRotated(); +} + +void WebPagePrivate::setViewportSize(const IntSize& transformedActualVisibleSize, bool ensureFocusElementVisible) +{ + if (m_pendingOrientation == -1 && transformedActualVisibleSize == this->transformedActualVisibleSize()) + return; + + // Suspend all screen updates to the backingstore to make sure no-one tries to blit + // while the window surface and the BackingStore are out of sync. + m_backingStore->d->suspendScreenAndBackingStoreUpdates(); + + // The screen rotation is a major state transition that in this case is not properly + // communicated to the backing store, since it does early return in most methods when + // not visible. + if (!m_visible || !m_backingStore->d->isActive()) + setShouldResetTilesWhenShown(true); + + bool hasPendingOrientation = m_pendingOrientation != -1; + if (hasPendingOrientation) + screenRotated(); + + // The window buffers might have been recreated, cleared, moved, etc., so: + m_backingStore->d->windowFrontBufferState()->clearBlittedRegion(); + m_backingStore->d->windowBackBufferState()->clearBlittedRegion(); + + IntSize viewportSizeBefore = actualVisibleSize(); + FloatPoint centerOfVisibleContentsRect = this->centerOfVisibleContentsRect(); + bool newVisibleRectContainsOldVisibleRect = (m_actualVisibleHeight <= transformedActualVisibleSize.height()) + && (m_actualVisibleWidth <= transformedActualVisibleSize.width()); + + bool atInitialScale = currentScale() == initialScale(); + bool atTop = !scrollPosition().y(); + bool atLeft = !scrollPosition().x(); + + // We need to reorient the visibleTileRect because the following code + // could cause BackingStore::transformChanged to be called, where it + // is used. + // It is only dependent on the transformedViewportSize which has been + // updated by now. + m_backingStore->d->createVisibleTileBuffer(); + + setDefaultLayoutSize(transformedActualVisibleSize); + + // Recompute our virtual viewport. + bool needsLayout = false; + static ViewportArguments defaultViewportArguments; + if (!(m_viewportArguments == defaultViewportArguments)) { + // We may need to infer the width and height for the viewport with respect to the rotation. + IntSize newVirtualViewport = recomputeVirtualViewportFromViewportArguments(); + ASSERT(!newVirtualViewport.isEmpty()); + m_webPage->setVirtualViewportSize(newVirtualViewport.width(), newVirtualViewport.height()); + m_mainFrame->view()->setUseFixedLayout(useFixedLayout()); + m_mainFrame->view()->setFixedLayoutSize(fixedLayoutSize()); + needsLayout = true; + } + + // We switch this strictly after recomputing our virtual viewport as zoomToFitScale is dependent + // upon these values and so is the virtual viewport recalculation. + m_actualVisibleWidth = transformedActualVisibleSize.width(); + m_actualVisibleHeight = transformedActualVisibleSize.height(); + + IntSize viewportSizeAfter = actualVisibleSize(); + + IntPoint offset(roundf((viewportSizeBefore.width() - viewportSizeAfter.width()) / 2.0), + roundf((viewportSizeBefore.height() - viewportSizeAfter.height()) / 2.0)); + + // As a special case, if we were anchored to the top left position at + // the beginning of the rotation then preserve that anchor. + if (atTop) + offset.setY(0); + if (atLeft) + offset.setX(0); + + // If we're about to overscroll, cap the offset to valid content. + IntPoint bottomRight( + scrollPosition().x() + viewportSizeAfter.width(), + scrollPosition().y() + viewportSizeAfter.height()); + + if (bottomRight.x() + offset.x() > contentsSize().width()) + offset.setX(contentsSize().width() - bottomRight.x()); + if (bottomRight.y() + offset.y() > contentsSize().height()) + offset.setY(contentsSize().height() - bottomRight.y()); + if (scrollPosition().x() + offset.x() < 0) + offset.setX(-scrollPosition().x()); + if (scrollPosition().y() + offset.y() < 0) + offset.setY(-scrollPosition().y()); + + // ...before scrolling, because the backing store will align its + // tile matrix with the viewport as reported by the ScrollView. + scrollBy(offset.x(), offset.y()); + notifyTransformedScrollChanged(); + + m_backingStore->d->orientationChanged(); + m_backingStore->d->actualVisibleSizeChanged(transformedActualVisibleSize); + + // Update view mode only after we have updated the actual + // visible size and reset the contents rect if necessary. + if (setViewMode(viewMode())) + needsLayout = true; + + // We need to update the viewport size of the WebCore::ScrollView... + updateViewportSize(!hasPendingOrientation /* setFixedReportedSize */, false /* sendResizeEvent */); + notifyTransformedContentsSizeChanged(); + + // If automatic zooming is disabled, prevent zooming below. + if (!m_webSettings->isZoomToFitOnLoad()) { + atInitialScale = false; + + // Normally, if the contents size is smaller than the layout width, + // we would zoom in. If zoom is disabled, we need to do something else, + // or there will be artifacts due to non-rendered areas outside of the + // contents size. If there is a virtual viewport, we are not allowed + // to modify the fixed layout size, however. + if (!hasVirtualViewport() && contentsSize().width() < m_defaultLayoutSize.width()) { + m_mainFrame->view()->setUseFixedLayout(useFixedLayout()); + m_mainFrame->view()->setFixedLayoutSize(m_defaultLayoutSize); + needsLayout = true; + } + } + + if (needsLayout) + setNeedsLayout(); + + // Need to resume so that the backingstore will start recording the invalidated + // rects from below. + m_backingStore->d->resumeScreenAndBackingStoreUpdates(BackingStore::None); + + // We might need to layout here to get a correct contentsSize so that zoomToFit + // is calculated correctly. + requestLayoutIfNeeded(); + + // As a special case if we were zoomed to the initial scale at the beginning + // of the rotation then preserve that zoom level even when it is zoomToFit. + double scale = atInitialScale ? initialScale() : currentScale(); + + // Do our own clamping. + scale = clampedScale(scale); + + if (hasPendingOrientation) { + // Set the fixed reported size here so that innerWidth|innerHeight works + // with this new scale. + TransformationMatrix rotationMatrix; + rotationMatrix.scale(scale); + IntRect viewportRect = IntRect(IntPoint::zero(), transformedActualVisibleSize); + IntRect actualVisibleRect = enclosingIntRect(rotationMatrix.inverse().mapRect(FloatRect(viewportRect))); + m_mainFrame->view()->setFixedReportedSize(actualVisibleRect.size()); + } + + // We're going to need to send a resize event to JavaScript because + // innerWidth and innerHeight depend on fixed reported size. + // This is how we support mobile pages where JavaScript resizes + // the page in order to get around the fixed layout size, e.g. + // google maps when it detects a mobile user agent. + if (shouldSendResizeEvent()) + m_mainFrame->eventHandler()->sendResizeEvent(); + + // As a special case if we were anchored to the top left position at the beginning + // of the rotation then preserve that anchor. + FloatPoint anchor = centerOfVisibleContentsRect; + if (atTop) + anchor.setY(0); + if (atLeft) + anchor.setX(0); + + // Try and zoom here with clamping on. + if (m_backingStore->d->shouldDirectRenderingToWindow()) { + bool success = zoomAboutPoint(scale, anchor, false /* enforceScaleClamping */, true /* forceRendering */); + if (!success && ensureFocusElementVisible) + ensureContentVisible(!newVisibleRectContainsOldVisibleRect); + } else if (!scheduleZoomAboutPoint(scale, anchor, false /* enforceScaleClamping */, true /* forceRendering */)) { + // Suspend all screen updates to the backingstore. + m_backingStore->d->suspendScreenAndBackingStoreUpdates(); + + // If the zoom failed, then we should still preserve the special case of scroll position. + IntPoint scrollPosition = this->scrollPosition(); + if (atTop) + scrollPosition.setY(0); + if (atLeft) + scrollPosition.setX(0); + setScrollPosition(scrollPosition); + + // These might have been altered even if we didn't zoom so notify the client. + notifyTransformedContentsSizeChanged(); + notifyTransformedScrollChanged(); + + if (!needsLayout) { + // The visible tiles for scroll must be up-to-date before we blit since we are not performing a layout. + m_backingStore->d->updateTilesForScrollOrNotRenderedRegion(); + } + + if (ensureFocusElementVisible) + ensureContentVisible(!newVisibleRectContainsOldVisibleRect); + + if (needsLayout) { + m_backingStore->d->resetTiles(true); + m_backingStore->d->updateTiles(false /* updateVisible */, false /* immediate */); + } + + // If we need layout then render and blit, otherwise just blit as our viewport has changed. + m_backingStore->d->resumeScreenAndBackingStoreUpdates(needsLayout ? BackingStore::RenderAndBlit : BackingStore::Blit); + } else if (ensureFocusElementVisible) + ensureContentVisible(!newVisibleRectContainsOldVisibleRect); +} + +void WebPage::setDefaultLayoutSize(int width, int height) +{ + IntSize size(width, height); + d->setDefaultLayoutSize(size); +} + +void WebPagePrivate::setDefaultLayoutSize(const IntSize& size) +{ + if (size == m_defaultLayoutSize) + return; + + IntSize screenSize = Platform::Graphics::Screen::size(); + ASSERT(size.width() <= screenSize.width() && size.height() <= screenSize.height()); + m_defaultLayoutSize = size.expandedTo(minimumLayoutSize).shrunkTo(screenSize); + + bool needsLayout = setViewMode(viewMode()); + if (needsLayout) { + setNeedsLayout(); + if (!isLoading()) + requestLayoutIfNeeded(); + } +} + +bool WebPage::mouseEvent(const Platform::MouseEvent& mouseEvent, bool* wheelDeltaAccepted) +{ + if (!d->m_mainFrame->view()) + return false; + + PluginView* pluginView = d->m_fullScreenPluginView.get(); + if (pluginView) + return d->dispatchMouseEventToFullScreenPlugin(pluginView, mouseEvent); + + if (mouseEvent.type() == Platform::MouseEvent::MouseAborted) { + d->m_mainFrame->eventHandler()->setMousePressed(false); + return false; + } + + d->m_pluginMayOpenNewTab = true; + + d->m_lastUserEventTimestamp = currentTime(); + int clickCount = (d->m_selectionHandler->isSelectionActive() || mouseEvent.type() != Platform::MouseEvent::MouseMove) ? 1 : 0; + + // Set the button type. + MouseButton buttonType = NoButton; + if (mouseEvent.isLeftButton()) + buttonType = LeftButton; + else if (mouseEvent.isRightButton()) + buttonType = RightButton; + else if (mouseEvent.isMiddleButton()) + buttonType = MiddleButton; + + // Create our event. + PlatformMouseEvent platformMouseEvent(d->mapFromTransformed(mouseEvent.position()), + d->mapFromTransformed(mouseEvent.screenPosition()), + toWebCoreMouseEventType(mouseEvent.type()), clickCount, buttonType, PointingDevice); + d->m_lastMouseEvent = platformMouseEvent; + bool success = d->handleMouseEvent(platformMouseEvent); + + if (mouseEvent.wheelTicks()) { + PlatformWheelEvent wheelEvent(d->mapFromTransformed(mouseEvent.position()), + d->mapFromTransformed(mouseEvent.screenPosition()), + 0, -mouseEvent.wheelDelta(), + 0, -mouseEvent.wheelTicks(), + ScrollByPixelWheelEvent, + false /* shiftKey */, false /* ctrlKey */, + false /* altKey */, false /* metaKey */); + if (wheelDeltaAccepted) + *wheelDeltaAccepted = d->handleWheelEvent(wheelEvent); + } else if (wheelDeltaAccepted) + *wheelDeltaAccepted = false; + + return success; +} + +bool WebPagePrivate::dispatchMouseEventToFullScreenPlugin(PluginView* plugin, const Platform::MouseEvent& event) +{ + NPEvent npEvent; + NPMouseEvent mouseEvent; + + mouseEvent.x = event.screenPosition().x(); + mouseEvent.y = event.screenPosition().y(); + + switch (event.type()) { + case Platform::MouseEvent::MouseButtonDown: + mouseEvent.type = MOUSE_BUTTON_DOWN; + m_pluginMouseButtonPressed = true; + break; + case Platform::MouseEvent::MouseButtonUp: + mouseEvent.type = MOUSE_BUTTON_UP; + m_pluginMouseButtonPressed = false; + break; + case Platform::MouseEvent::MouseMove: + mouseEvent.type = MOUSE_MOTION; + break; + default: + return false; + } + + mouseEvent.flags = 0; + mouseEvent.button = m_pluginMouseButtonPressed; + + npEvent.type = NP_MouseEvent; + npEvent.data = &mouseEvent; + + return plugin->dispatchFullScreenNPEvent(npEvent); +} + +bool WebPagePrivate::handleMouseEvent(PlatformMouseEvent& mouseEvent) +{ + EventHandler* eventHandler = m_mainFrame->eventHandler(); + + if (mouseEvent.eventType() == MouseEventMoved) + return eventHandler->mouseMoved(mouseEvent); + + if (mouseEvent.eventType() == MouseEventScroll) + return true; + + Node* node = 0; + if (mouseEvent.inputMethod() == TouchScreen) { + const FatFingersResult lastFatFingersResult = m_touchEventHandler->lastFatFingersResult(); + + // Fat fingers can deal with shadow content. + node = lastFatFingersResult.node(FatFingersResult::ShadowContentNotAllowed); + } + + if (!node) { + HitTestResult result = eventHandler->hitTestResultAtPoint(mapFromViewportToContents(mouseEvent.pos()), false /*allowShadowContent*/); + node = result.innerNode(); + } + + if (mouseEvent.eventType() == MouseEventPressed) { + if (m_inputHandler->willOpenPopupForNode(node)) { + // Do not allow any human generated mouse or keyboard events to select <option>s in the list box + // because we use a pop up dialog to handle the actual selections. This prevents options from + // being selected prior to displaying the pop up dialog. The contents of the listbox are for + // display only. + // + // FIXME: We explicitly do not forward this event to WebCore so as to preserve symmetry with + // the MouseEventReleased handling (below). This has the side-effect that mousedown events + // are not fired for human generated mouse press events. See RIM Bug #1579. + + // We do focus <select>/<option> on mouse down so that a Focus event is fired and have the + // element painted in its focus state on repaint. + ASSERT(node->isElementNode()); + if (node->isElementNode()) { + Element* element = static_cast<Element*>(node); + element->focus(); + } + } else + eventHandler->handleMousePressEvent(mouseEvent); + } else if (mouseEvent.eventType() == MouseEventReleased) { + // FIXME: For <select> and <options> elements, we explicitly do not forward this event to WebCore so + // as to preserve symmetry with the MouseEventPressed handling (above). This has the side-effect that + // mouseup events are not fired on such elements for human generated mouse release events. See RIM Bug #1579. + if (!m_inputHandler->didNodeOpenPopup(node)) + eventHandler->handleMouseReleaseEvent(mouseEvent); + } + + return true; +} + +bool WebPagePrivate::handleWheelEvent(PlatformWheelEvent& wheelEvent) +{ + return m_mainFrame->eventHandler()->handleWheelEvent(wheelEvent); +} + +bool WebPage::touchEvent(const Platform::TouchEvent& event) +{ +#if DEBUG_TOUCH_EVENTS + switch (event.m_type) { + case Platform::TouchEvent::TouchEnd: + Platform::log(Platform::LogLevelCritical, "WebPage::touchEvent Touch End"); + break; + case Platform::TouchEvent::TouchStart: + Platform::log(Platform::LogLevelCritical, "WebPage::touchEvent Touch Start"); + break; + case Platform::TouchEvent::TouchMove: + Platform::log(Platform::LogLevelCritical, "WebPage::touchEvent Touch Move"); + break; + case Platform::TouchEvent::TouchCancel: + Platform::log(Platform::LogLevelCritical, "WebPage::touchCancel Touch Cancel"); + break; + } + + for (unsigned i = 0; i < event.m_points.size(); i++) { + switch (event.m_points[i].m_state) { + case Platform::TouchPoint::TouchPressed: + Platform::log(Platform::LogLevelCritical, "WebPage::touchEvent %d Touch Pressed (%d, %d)", event.m_points[i].m_id, event.m_points[i].m_pos.x(), event.m_points[i].m_pos.y()); + break; + case Platform::TouchPoint::TouchReleased: + Platform::log(Platform::LogLevelCritical, "WebPage::touchEvent %d Touch Released (%d, %d)", event.m_points[i].m_id, event.m_points[i].m_pos.x(), event.m_points[i].m_pos.y()); + break; + case Platform::TouchPoint::TouchMoved: + Platform::log(Platform::LogLevelCritical, "WebPage::touchEvent %d Touch Moved (%d, %d)", event.m_points[i].m_id, event.m_points[i].m_pos.x(), event.m_points[i].m_pos.y()); + break; + case Platform::TouchPoint::TouchStationary: + Platform::log(Platform::LogLevelCritical, "WebPage::touchEvent %d Touch Stationary (%d, %d)", event.m_points[i].m_id, event.m_points[i].m_pos.x(), event.m_points[i].m_pos.y()); + break; + } + } +#endif + +#if ENABLE(TOUCH_EVENTS) + PluginView* pluginView = d->m_fullScreenPluginView.get(); + if (pluginView) + return d->dispatchTouchEventToFullScreenPlugin(pluginView, event); + + if (!d->m_mainFrame) + return false; + + Platform::TouchEvent tEvent = event; + for (unsigned i = 0; i < event.m_points.size(); i++) { + tEvent.m_points[i].m_pos = d->mapFromTransformed(tEvent.m_points[i].m_pos); + tEvent.m_points[i].m_screenPos = d->mapFromTransformed(tEvent.m_points[i].m_screenPos); + } + + Platform::Gesture tapGesture; + if (event.hasGesture(Platform::Gesture::SingleTap)) + d->m_pluginMayOpenNewTab = true; + else if (tEvent.m_type == Platform::TouchEvent::TouchStart || tEvent.m_type == Platform::TouchEvent::TouchCancel) + d->m_pluginMayOpenNewTab = false; + + bool handled = false; + + if (d->m_needTouchEvents && !event.hasGesture(Platform::Gesture::Injected)) + handled = d->m_mainFrame->eventHandler()->handleTouchEvent(PlatformTouchEvent(&tEvent)); + + // Unpress mouse if touch end is consumed by a JavaScript touch handler, otherwise the mouse state will remain pressed + // which could either mess up the internal mouse state or start text selection on the next mouse move/down. + if (tEvent.m_type == Platform::TouchEvent::TouchEnd && handled && d->m_mainFrame->eventHandler()->mousePressed()) + d->m_touchEventHandler->touchEventCancel(); + + if (d->m_preventDefaultOnTouchStart) { + if (tEvent.m_type == Platform::TouchEvent::TouchEnd || tEvent.m_type == Platform::TouchEvent::TouchCancel) + d->m_preventDefaultOnTouchStart = false; + return true; + } + + if (handled) { + if (tEvent.m_type == Platform::TouchEvent::TouchStart) + d->m_preventDefaultOnTouchStart = true; + return true; + } + + if (event.hasGesture(Platform::Gesture::TouchHold)) + d->m_touchEventHandler->touchHoldEvent(); +#endif + + return false; +} + +void WebPage::setScrollOriginPoint(const Platform::IntPoint& point) +{ + Platform::IntPoint untransformedPoint = d->mapFromTransformed(point); + d->setScrollOriginPoint(untransformedPoint); +} + +void WebPagePrivate::setScrollOriginPoint(const Platform::IntPoint& point) +{ + m_inRegionScrollStartingNode = 0; + + if (!m_hasInRegionScrollableAreas) + return; + + m_client->notifyInRegionScrollingStartingPointChanged(inRegionScrollableAreasForPoint(point)); +} + +bool WebPagePrivate::dispatchTouchEventToFullScreenPlugin(PluginView* plugin, const Platform::TouchEvent& event) +{ + NPTouchEvent npTouchEvent; + + if (event.hasGesture(Platform::Gesture::DoubleTap)) + npTouchEvent.type = TOUCH_EVENT_DOUBLETAP; + else if (event.hasGesture(Platform::Gesture::TouchHold)) + npTouchEvent.type = TOUCH_EVENT_TOUCHHOLD; + else { + switch (event.m_type) { + case Platform::TouchEvent::TouchStart: + npTouchEvent.type = TOUCH_EVENT_START; + break; + case Platform::TouchEvent::TouchEnd: + npTouchEvent.type = TOUCH_EVENT_END; + break; + case Platform::TouchEvent::TouchMove: + npTouchEvent.type = TOUCH_EVENT_MOVE; + break; + case Platform::TouchEvent::TouchCancel: + npTouchEvent.type = TOUCH_EVENT_CANCEL; + break; + default: + return false; + } + } + + npTouchEvent.points = 0; + npTouchEvent.size = event.m_points.size(); + if (npTouchEvent.size) { + npTouchEvent.points = new NPTouchPoint[npTouchEvent.size]; + for (int i = 0; i < npTouchEvent.size; i++) { + npTouchEvent.points[i].touchId = event.m_points[i].m_id; + npTouchEvent.points[i].clientX = event.m_points[i].m_screenPos.x(); + npTouchEvent.points[i].clientY = event.m_points[i].m_screenPos.y(); + npTouchEvent.points[i].screenX = event.m_points[i].m_screenPos.x(); + npTouchEvent.points[i].screenY = event.m_points[i].m_screenPos.y(); + npTouchEvent.points[i].pageX = event.m_points[i].m_pos.x(); + npTouchEvent.points[i].pageY = event.m_points[i].m_pos.y(); + } + } + + NPEvent npEvent; + npEvent.type = NP_TouchEvent; + npEvent.data = &npTouchEvent; + + bool handled = plugin->dispatchFullScreenNPEvent(npEvent); + + if (npTouchEvent.type == TOUCH_EVENT_DOUBLETAP && !handled) { + // Send Touch Up if double tap not consumed. + npTouchEvent.type = TOUCH_EVENT_END; + npEvent.data = &npTouchEvent; + handled = plugin->dispatchFullScreenNPEvent(npEvent); + } + delete[] npTouchEvent.points; + return handled; +} + +bool WebPage::touchPointAsMouseEvent(const Platform::TouchPoint& point) +{ + PluginView* pluginView = d->m_fullScreenPluginView.get(); + if (pluginView) + return d->dispatchTouchPointAsMouseEventToFullScreenPlugin(pluginView, point); + + d->m_lastUserEventTimestamp = currentTime(); + + Platform::TouchPoint tPoint = point; + tPoint.m_pos = d->mapFromTransformed(tPoint.m_pos); + tPoint.m_screenPos = d->mapFromTransformed(tPoint.m_screenPos); + + return d->m_touchEventHandler->handleTouchPoint(tPoint); +} + +bool WebPagePrivate::dispatchTouchPointAsMouseEventToFullScreenPlugin(PluginView* pluginView, const Platform::TouchPoint& point) +{ + NPEvent npEvent; + NPMouseEvent mouse; + + switch (point.m_state) { + case Platform::TouchPoint::TouchPressed: + mouse.type = MOUSE_BUTTON_DOWN; + break; + case Platform::TouchPoint::TouchReleased: + mouse.type = MOUSE_BUTTON_UP; + break; + case Platform::TouchPoint::TouchMoved: + mouse.type = MOUSE_MOTION; + break; + case Platform::TouchPoint::TouchStationary: + return false; + } + + mouse.x = point.m_screenPos.x(); + mouse.y = point.m_screenPos.y(); + mouse.button = mouse.type != MOUSE_BUTTON_UP; + mouse.flags = 0; + npEvent.type = NP_MouseEvent; + npEvent.data = &mouse; + + return pluginView->dispatchFullScreenNPEvent(npEvent); +} + +void WebPage::touchEventCancel() +{ + d->m_pluginMayOpenNewTab = false; + d->m_touchEventHandler->touchEventCancel(); +} + +void WebPage::touchEventCancelAndClearFocusedNode() +{ + d->m_touchEventHandler->touchEventCancelAndClearFocusedNode(); +} + +Frame* WebPagePrivate::focusedOrMainFrame() const +{ + return m_page->focusController()->focusedOrMainFrame(); +} + +void WebPagePrivate::clearFocusNode() +{ + Frame* frame = focusedOrMainFrame(); + if (!frame) + return; + ASSERT(frame->document()); + + if (frame->document()->focusedNode()) + frame->page()->focusController()->setFocusedNode(0, frame); +} + +bool WebPagePrivate::scrollNodeRecursively(Node* node, const IntSize& delta) +{ + if (delta.isZero()) + return true; + + if (!node) + return false; + + RenderObject* renderer = node->renderer(); + if (!renderer) + return false; + + FrameView* view = renderer->view()->frameView(); + if (!view) + return false; + + // Try scrolling the renderer. + if (scrollRenderer(renderer, delta)) + return true; + + // We've hit the page, don't scroll it and return false. + if (view == m_mainFrame->view()) + return false; + + // Try scrolling the FrameView. + if (canScrollInnerFrame(view->frame())) { + IntSize viewDelta = delta; + IntPoint newViewOffset = view->scrollPosition(); + IntPoint maxViewOffset = view->maximumScrollPosition(); + adjustScrollDelta(maxViewOffset, newViewOffset, viewDelta); + + if (!viewDelta.isZero()) { + view->setCanBlitOnScroll(false); + + BackingStoreClient* backingStoreClient = backingStoreClientForFrame(view->frame()); + if (backingStoreClient) { + backingStoreClient->setIsClientGeneratedScroll(true); + backingStoreClient->setIsScrollNotificationSuppressed(true); + } + + m_inRegionScrollStartingNode = view->frame()->document(); + + view->scrollBy(viewDelta); + + if (backingStoreClient) { + backingStoreClient->setIsClientGeneratedScroll(false); + backingStoreClient->setIsScrollNotificationSuppressed(false); + } + + return true; + } + } + + // Try scrolling the node of the enclosing frame. + Frame* frame = node->document()->frame(); + if (frame) { + Node* ownerNode = frame->ownerElement(); + if (scrollNodeRecursively(ownerNode, delta)) + return true; + } + + return false; +} + +void WebPagePrivate::adjustScrollDelta(const IntPoint& maxOffset, const IntPoint& currentOffset, IntSize& delta) const +{ + if (currentOffset.x() + delta.width() > maxOffset.x()) + delta.setWidth(min(maxOffset.x() - currentOffset.x(), delta.width())); + + if (currentOffset.x() + delta.width() < 0) + delta.setWidth(max(-currentOffset.x(), delta.width())); + + if (currentOffset.y() + delta.height() > maxOffset.y()) + delta.setHeight(min(maxOffset.y() - currentOffset.y(), delta.height())); + + if (currentOffset.y() + delta.height() < 0) + delta.setHeight(max(-currentOffset.y(), delta.height())); +} + +static Node* enclosingLayerNode(RenderLayer*); + +bool WebPagePrivate::scrollRenderer(RenderObject* renderer, const IntSize& delta) +{ + RenderLayer* layer = renderer->enclosingLayer(); + if (!layer) + return false; + + // Try to scroll layer. + bool restrictedByLineClamp = false; + if (renderer->parent()) + restrictedByLineClamp = !renderer->parent()->style()->lineClamp().isNone(); + + if (renderer->hasOverflowClip() && !restrictedByLineClamp) { + IntSize layerDelta = delta; + IntPoint maxOffset(layer->scrollWidth() - layer->renderBox()->clientWidth(), layer->scrollHeight() - layer->renderBox()->clientHeight()); + IntPoint currentOffset(layer->scrollXOffset(), layer->scrollYOffset()); + adjustScrollDelta(maxOffset, currentOffset, layerDelta); + if (!layerDelta.isZero()) { + m_inRegionScrollStartingNode = enclosingLayerNode(layer); + IntPoint newOffset = currentOffset + layerDelta; + layer->scrollToOffset(newOffset.x(), newOffset.y()); + renderer->repaint(true); + return true; + } + } + + while (layer = layer->parent()) { + if (canScrollRenderBox(layer->renderBox())) + return scrollRenderer(layer->renderBox(), delta); + } + + return false; +} + +static void handleScrolling(unsigned short character, WebPagePrivate* scroller) +{ + const int scrollFactor = 20; + int dx = 0, dy = 0; + switch (character) { + case KEYCODE_LEFT: + dx = -scrollFactor; + break; + case KEYCODE_RIGHT: + dx = scrollFactor; + break; + case KEYCODE_UP: + dy = -scrollFactor; + break; + case KEYCODE_DOWN: + dy = scrollFactor; + break; + case KEYCODE_PG_UP: + ASSERT(scroller); + dy = scrollFactor - scroller->actualVisibleSize().height(); + break; + case KEYCODE_PG_DOWN: + ASSERT(scroller); + dy = scroller->actualVisibleSize().height() - scrollFactor; + break; + } + + if (dx || dy) { + // Don't use the scrollBy function because it triggers the scroll as originating from BlackBerry + // but then it expects a separate invalidate which isn't sent in this case. + ASSERT(scroller && scroller->m_mainFrame && scroller->m_mainFrame->view()); + IntPoint pos(scroller->scrollPosition() + IntSize(dx, dy)); + + // Prevent over scrolling for arrows and Page up/down. + if (pos.x() < 0) + pos.setX(0); + if (pos.y() < 0) + pos.setY(0); + if (pos.x() + scroller->actualVisibleSize().width() > scroller->contentsSize().width()) + pos.setX(scroller->contentsSize().width() - scroller->actualVisibleSize().width()); + if (pos.y() + scroller->actualVisibleSize().height() > scroller->contentsSize().height()) + pos.setY(scroller->contentsSize().height() - scroller->actualVisibleSize().height()); + + scroller->m_mainFrame->view()->setScrollPosition(pos); + scroller->m_client->scrollChanged(pos); + } +} + +bool WebPage::keyEvent(const Platform::KeyboardEvent& keyboardEvent) +{ + if (!d->m_mainFrame->view()) + return false; + + ASSERT(d->m_page->focusController()); + + bool handled = d->m_inputHandler->handleKeyboardInput(keyboardEvent); + + if (!handled && keyboardEvent.type() == Platform::KeyboardEvent::KeyDown && !d->m_inputHandler->isInputMode()) { + IntPoint previousPos = d->scrollPosition(); + handleScrolling(keyboardEvent.character(), d); + handled = previousPos != d->scrollPosition(); + } + + return handled; +} + +bool WebPage::deleteTextRelativeToCursor(unsigned int leftOffset, unsigned int rightOffset) +{ + return d->m_inputHandler->deleteTextRelativeToCursor(leftOffset, rightOffset); +} + +spannable_string_t* WebPage::selectedText(int32_t flags) +{ + return d->m_inputHandler->selectedText(flags); +} + +spannable_string_t* WebPage::textBeforeCursor(int32_t length, int32_t flags) +{ + return d->m_inputHandler->textBeforeCursor(length, flags); +} + +spannable_string_t* WebPage::textAfterCursor(int32_t length, int32_t flags) +{ + return d->m_inputHandler->textAfterCursor(length, flags); +} + +extracted_text_t* WebPage::extractedTextRequest(extracted_text_request_t* request, int32_t flags) +{ + return d->m_inputHandler->extractedTextRequest(request, flags); +} + +int32_t WebPage::setComposingRegion(int32_t start, int32_t end) +{ + return d->m_inputHandler->setComposingRegion(start, end); +} + +int32_t WebPage::finishComposition() +{ + return d->m_inputHandler->finishComposition(); +} + +int32_t WebPage::setComposingText(spannable_string_t* spannableString, int32_t relativeCursorPosition) +{ + return d->m_inputHandler->setComposingText(spannableString, relativeCursorPosition); +} + +int32_t WebPage::commitText(spannable_string_t* spannableString, int32_t relativeCursorPosition) +{ + return d->m_inputHandler->commitText(spannableString, relativeCursorPosition); +} + +void WebPage::spellCheckingEnabled(bool enabled) +{ + static_cast<EditorClientBlackBerry*>(d->m_page->editorClient())->enableSpellChecking(enabled); +} + +void WebPage::selectionCancelled() +{ + d->m_selectionHandler->cancelSelection(); +} + +bool WebPage::selectionContains(const Platform::IntPoint& point) +{ + return d->m_selectionHandler->selectionContains(d->mapFromTransformed(point)); +} + +WebString WebPage::title() const +{ + if (d->m_mainFrame->document()) + return d->m_mainFrame->loader()->documentLoader()->title().string(); + return WebString(); +} + +WebString WebPage::selectedText() const +{ + return d->m_selectionHandler->selectedText(); +} + +WebString WebPage::cutSelectedText() +{ + WebString selectedText = d->m_selectionHandler->selectedText(); + if (!selectedText.isEmpty()) + d->m_inputHandler->deleteSelection(); + return selectedText; +} + +void WebPage::insertText(const WebString& string) +{ + d->m_inputHandler->insertText(string); +} + +void WebPage::clearCurrentInputField() +{ + d->m_inputHandler->clearField(); +} + +void WebPage::cut() +{ + d->m_inputHandler->cut(); +} + +void WebPage::copy() +{ + d->m_inputHandler->copy(); +} + +void WebPage::paste() +{ + d->m_inputHandler->paste(); +} + +void WebPage::setSelection(const Platform::IntPoint& startPoint, const Platform::IntPoint& endPoint) +{ + // Transform this events coordinates to webkit content coordinates. + // FIXME: Don't transform the sentinel, because it may be transformed to a floating number + // which could be rounded to 0 or other numbers. This workaround should be removed after + // the error of roundUntransformedPoint() is fixed. + bool invalidPoint = IntPoint(startPoint) == DOMSupport::InvalidPoint; + IntPoint start = invalidPoint ? DOMSupport::InvalidPoint : d->mapFromTransformed(startPoint); + invalidPoint = IntPoint(endPoint) == DOMSupport::InvalidPoint; + IntPoint end = invalidPoint ? DOMSupport::InvalidPoint : d->mapFromTransformed(endPoint); + + d->m_selectionHandler->setSelection(start, end); +} + +void WebPage::setCaretPosition(const Platform::IntPoint& position) +{ + // Handled by selection handler as it's point based. + // Transform this events coordinates to webkit content coordinates. + d->m_selectionHandler->setCaretPosition(d->mapFromTransformed(position)); +} + +void WebPage::selectAtPoint(const Platform::IntPoint& location) +{ + // Transform this events coordinates to webkit content coordinates if it + // is not the sentinel value. + IntPoint selectionLocation = + IntPoint(location) == DOMSupport::InvalidPoint ? + DOMSupport::InvalidPoint : + d->mapFromTransformed(location); + + d->m_selectionHandler->selectAtPoint(selectionLocation); +} + +// Returned scroll position is in transformed coordinates. +Platform::IntPoint WebPage::scrollPosition() const +{ + return d->transformedScrollPosition(); +} + +// Setting the scroll position is in transformed coordinates. +void WebPage::setScrollPosition(const Platform::IntPoint& point) +{ + if (d->transformedPointEqualsUntransformedPoint(point, d->scrollPosition())) + return; + + // If the user recently performed an event, this new scroll position + // could possibly be a result of that. Or not, this is just a heuristic. + if (currentTime() - d->m_lastUserEventTimestamp < manualScrollInterval) + d->m_userPerformedManualScroll = true; + + d->m_backingStoreClient->setIsClientGeneratedScroll(true); + d->m_mainFrame->view()->setCanOverscroll(true); + d->setScrollPosition(d->mapFromTransformed(point)); + d->m_mainFrame->view()->setCanOverscroll(false); + d->m_backingStoreClient->setIsClientGeneratedScroll(false); +} + +WebString WebPage::textEncoding() +{ + Frame* frame = d->focusedOrMainFrame(); + if (!frame) + return ""; + + Document* document = frame->document(); + if (!document) + return ""; + + return document->loader()->writer()->encoding(); +} + +WebString WebPage::forcedTextEncoding() +{ + Frame* frame = d->focusedOrMainFrame(); + if (!frame) + return ""; + + Document* document = frame->document(); + if (!document) + return ""; + + return document->loader()->overrideEncoding(); +} + +void WebPage::setForcedTextEncoding(const char* encoding) +{ + if (encoding && d->focusedOrMainFrame() && d->focusedOrMainFrame()->loader() && d->focusedOrMainFrame()->loader()) + return d->focusedOrMainFrame()->loader()->reloadWithOverrideEncoding(encoding); +} + +// FIXME: Move to DOMSupport. +bool WebPagePrivate::canScrollInnerFrame(Frame* frame) const +{ + if (!frame || !frame->view()) + return false; + + // Not having an owner element means that we are on the mainframe. + if (!frame->ownerElement()) + return false; + + ASSERT(frame != m_mainFrame); + + IntSize visibleSize = frame->view()->visibleContentRect().size(); + IntSize contentsSize = frame->view()->contentsSize(); + + bool canBeScrolled = contentsSize.height() > visibleSize.height() || contentsSize.width() > visibleSize.width(); + + // Lets also consider the 'overflow-{x,y} property set directly to the {i}frame tag. + return canBeScrolled && (frame->ownerElement()->scrollingMode() != ScrollbarAlwaysOff); +} + +// The RenderBox::canbeScrolledAndHasScrollableArea method returns true for the +// following scenario, for example: +// (1) a div that has a vertical overflow but no horizontal overflow +// with overflow-y: hidden and overflow-x: auto set. +// The version below fixes it. +// FIXME: Fix RenderBox::canBeScrolledAndHasScrollableArea method instead. +bool WebPagePrivate::canScrollRenderBox(RenderBox* box) +{ + if (!box || !box->hasOverflowClip()) + return false; + + if (box->scrollsOverflowX() && (box->scrollWidth() != box->clientWidth()) + || box->scrollsOverflowY() && (box->scrollHeight() != box->clientHeight())) + return true; + + Node* node = box->node(); + return node && (node->rendererIsEditable() || node->isDocumentNode()); +} + +static RenderLayer* parentLayer(RenderLayer* layer) +{ + ASSERT(layer); + + if (layer->parent()) + return layer->parent(); + + RenderObject* renderer = layer->renderer(); + if (renderer->document() && renderer->document()->ownerElement() && renderer->document()->ownerElement()->renderer()) + return renderer->document()->ownerElement()->renderer()->enclosingLayer(); + + return 0; +} + +// FIXME: Make RenderLayer::enclosingElement public so this one can be removed. +static Node* enclosingLayerNode(RenderLayer* layer) +{ + for (RenderObject* r = layer->renderer(); r; r = r->parent()) { + if (Node* e = r->node()) + return e; + } + ASSERT_NOT_REACHED(); + return 0; +} + +static void pushBackInRegionScrollable(std::vector<Platform::ScrollViewBase>& vector, InRegionScrollableArea scroller, WebPagePrivate* webPage) +{ + ASSERT(webPage); + ASSERT(!scroller.isNull()); + + scroller.setCanPropagateScrollingToEnclosingScrollable(!isNonRenderViewFixedPositionedContainer(scroller.layer())); + vector.push_back(scroller); + if (vector.size() == 1) { + // FIXME: Use RenderLayer::renderBox()->node() instead? + webPage->m_inRegionScrollStartingNode = enclosingLayerNode(scroller.layer()); + } +} + +std::vector<Platform::ScrollViewBase> WebPagePrivate::inRegionScrollableAreasForPoint(const Platform::IntPoint& point) +{ + std::vector<Platform::ScrollViewBase> validReturn; + std::vector<Platform::ScrollViewBase> emptyReturn; + + HitTestResult result = m_mainFrame->eventHandler()->hitTestResultAtPoint(mapFromViewportToContents(point), false /*allowShadowContent*/); + Node* node = result.innerNonSharedNode(); + if (!node) + return emptyReturn; + + RenderObject* renderer = node->renderer(); + // FIXME: Validate with elements with visibility:hidden. + if (!renderer) + return emptyReturn; + + RenderLayer* layer = renderer->enclosingLayer(); + + do { + RenderObject* renderer = layer->renderer(); + + if (renderer->isRenderView()) { + if (RenderView* renderView = toRenderView(renderer)) { + FrameView* view = renderView->frameView(); + if (!view) + return emptyReturn; + + if (canScrollInnerFrame(view->frame())) { + pushBackInRegionScrollable(validReturn, InRegionScrollableArea(this, layer), this); + continue; + } + } + } else if (canScrollRenderBox(layer->renderBox())) { + pushBackInRegionScrollable(validReturn, InRegionScrollableArea(this, layer), this); + continue; + } + + // If we run into a fix positioned layer, set the last scrollable in-region object + // as not able to propagate scroll to its parent scrollable. + if (isNonRenderViewFixedPositionedContainer(layer) && validReturn.size()) { + Platform::ScrollViewBase& end = validReturn.back(); + end.setCanPropagateScrollingToEnclosingScrollable(false); + } + + } while (layer = parentLayer(layer)); + + if (validReturn.empty()) + return emptyReturn; + + return validReturn; +} + +BackingStore* WebPage::backingStore() const +{ + return d->m_backingStore; +} + +bool WebPage::zoomToFit() +{ + if (d->contentsSize().isEmpty() || !d->isUserScalable()) + return false; + + d->m_userPerformedManualZoom = true; + + // TODO: We may need to use (0,0) as the anchor point when textReflow is enabled. + // IF the minimum font size is ginormous, we may still want the scroll position to be 0,0. + return d->zoomAboutPoint(d->zoomToFitScale(), d->centerOfVisibleContentsRect()); +} + +void WebPagePrivate::setTextReflowAnchorPoint(const Platform::IntPoint& focalPoint) +{ + // Should only be invoked when text reflow is enabled. + ASSERT(m_webPage->settings()->textReflowMode() == WebSettings::TextReflowEnabled); + + m_currentPinchZoomNode = bestNodeForZoomUnderPoint(focalPoint); + if (!m_currentPinchZoomNode) + return; + + IntRect nodeRect = rectForNode(m_currentPinchZoomNode.get()); + m_anchorInNodeRectRatio.set(static_cast<float>(mapFromTransformed(focalPoint).x() - nodeRect.x()) / nodeRect.width(), + static_cast<float>(mapFromTransformed(focalPoint).y() - nodeRect.y()) / nodeRect.height()); +} + +bool WebPage::pinchZoomAboutPoint(double scale, int x, int y) +{ + IntPoint anchor(x, y); + d->m_userPerformedManualZoom = true; + d->m_userPerformedManualScroll = true; + + if (d->m_webPage->settings()->textReflowMode() == WebSettings::TextReflowEnabled) { + d->setTextReflowAnchorPoint(anchor); + // Theoretically, d->nodeForZoomUnderPoint(anchor) can return null. + if (!d->m_currentPinchZoomNode) + return false; + } + + return d->zoomAboutPoint(scale, d->mapFromTransformed(anchor)); +} + +#if ENABLE(VIEWPORT_REFLOW) +void WebPagePrivate::toggleTextReflowIfEnabledForBlockZoomOnly(bool shouldEnableTextReflow) +{ + if (m_webPage->settings()->textReflowMode() == WebSettings::TextReflowEnabledOnlyForBlockZoom) + m_page->settings()->setTextReflowEnabled(shouldEnableTextReflow); +} +#endif + +bool WebPage::blockZoom(int x, int y) +{ + if (!d->m_mainFrame->view() || !d->isUserScalable()) + return false; + + Node* node = d->bestNodeForZoomUnderPoint(IntPoint(x, y)); + if (!node) + return false; + + IntRect nodeRect = d->rectForNode(node); + IntRect blockRect; + bool endOfBlockZoomMode = d->compareNodesForBlockZoom(d->m_currentBlockZoomAdjustedNode.get(), node); + const double oldScale = d->m_transformationMatrix->m11(); + double newScale = 0; + const double margin = endOfBlockZoomMode ? 0 : blockZoomMargin * 2 * oldScale; + bool isFirstZoom = false; + + if (endOfBlockZoomMode) { + // End of block zoom mode + IntRect rect = d->blockZoomRectForNode(node); + blockRect = IntRect(0, rect.y(), d->transformedContentsSize().width(), d->transformedContentsSize().height() - rect.y()); + d->m_shouldReflowBlock = false; + } else { + // Start/continue block zoom mode + Node* tempBlockZoomAdjustedNode = d->m_currentBlockZoomAdjustedNode.get(); + blockRect = d->blockZoomRectForNode(node); + + // Don't use a block if it is too close to the size of the actual contents. + // We allow this for images only so that they can be zoomed tight to the screen. + if (!node->hasTagName(HTMLNames::imgTag)) { + IntRect tRect = d->mapFromTransformed(blockRect); + int blockArea = tRect.width() * tRect.height(); + int pageArea = d->contentsSize().width() * d->contentsSize().height(); + double blockToPageRatio = static_cast<double>(1 - blockArea / pageArea); + if (blockToPageRatio < minimumExpandingRatio) { + // Restore old adjust node because zoom was canceled. + d->m_currentBlockZoomAdjustedNode = tempBlockZoomAdjustedNode; + return false; + } + } + + if (blockRect.isEmpty() || !blockRect.width() || !blockRect.height()) + return false; + + if (!d->m_currentBlockZoomNode.get()) + isFirstZoom = true; + + d->m_currentBlockZoomNode = node; + d->m_shouldReflowBlock = true; + } + + newScale = std::min(d->newScaleForBlockZoomRect(blockRect, oldScale, margin), d->maxBlockZoomScale()); + newScale = std::max(newScale, minimumScale()); + +#if DEBUG_BLOCK_ZOOM + // Render the double tap point for visual reference. + IntRect renderRect(x, y, 1, 1); + renderRect = d->mapFromTransformedContentsToTransformedViewport(renderRect); + IntSize viewportSize = d->transformedViewportSize(); + renderRect.intersect(IntRect(0, 0, viewportSize.width(), viewportSize.height())); + d->m_backingStore->d->clearWindow(renderRect, 0, 0, 0); + d->m_backingStore->d->invalidateWindow(renderRect); + + // Uncomment this to return in order to see the blocks being selected. + // d->m_client->zoomChanged(isMinZoomed(), isMaxZoomed(), isAtInitialZoom(), currentZoomLevel()); + // return true; +#endif + +#if ENABLE(VIEWPORT_REFLOW) + // If reflowing, adjust the reflow-width of text node to make sure the font is a reasonable size. + if (d->m_currentBlockZoomNode && d->m_shouldReflowBlock && settings()->textReflowMode() != WebSettings::TextReflowDisabled) { + RenderObject* renderer = d->m_currentBlockZoomNode->renderer(); + if (renderer && renderer->isText()) { + double newFontSize = renderer->style()->fontSize() * newScale; + if (newFontSize < d->m_webSettings->defaultFontSize()) { + newScale = std::min(static_cast<double>(d->m_webSettings->defaultFontSize()) / renderer->style()->fontSize(), d->maxBlockZoomScale()); + newScale = std::max(newScale, minimumScale()); + } + blockRect.setWidth(oldScale * static_cast<double>(d->transformedActualVisibleSize().width()) / newScale); + // Re-calculate the scale here to take in to account the margin. + newScale = std::min(d->newScaleForBlockZoomRect(blockRect, oldScale, margin), d->maxBlockZoomScale()); + newScale = std::max(newScale, minimumScale()); // Still, it's not allowed to be smaller than minimum scale. + } + } +#endif + + // Align the zoomed block in the screen. + double newBlockHeight = d->mapFromTransformed(blockRect).height(); + double newBlockWidth = d->mapFromTransformed(blockRect).width(); + double scaledViewportWidth = static_cast<double>(d->actualVisibleSize().width()) * oldScale / newScale; + double scaledViewportHeight = static_cast<double>(d->actualVisibleSize().height()) * oldScale / newScale; + double dx = std::max(0.0, (scaledViewportWidth - newBlockWidth) / 2.0); + double dy = std::max(0.0, (scaledViewportHeight - newBlockHeight) / 2.0); + + RenderObject* renderer = d->m_currentBlockZoomAdjustedNode->renderer(); + FloatPoint anchor; + FloatPoint topLeftPoint(d->mapFromTransformed(blockRect).location()); + if (renderer && renderer->isText()) { + ETextAlign textAlign = renderer->style()->textAlign(); + switch (textAlign) { + case CENTER: + case WEBKIT_CENTER: + anchor = FloatPoint(nodeRect.x() + (nodeRect.width() - scaledViewportWidth) / 2, topLeftPoint.y()); + break; + case LEFT: + case WEBKIT_LEFT: + anchor = topLeftPoint; + break; + case RIGHT: + case WEBKIT_RIGHT: + anchor = FloatPoint(nodeRect.x() + nodeRect.width() - scaledViewportWidth, topLeftPoint.y()); + break; + case TAAUTO: + case JUSTIFY: + default: + if (renderer->style()->isLeftToRightDirection()) + anchor = topLeftPoint; + else + anchor = FloatPoint(nodeRect.x() + nodeRect.width() - scaledViewportWidth, topLeftPoint.y()); + break; + } + } else + anchor = renderer->style()->isLeftToRightDirection() ? topLeftPoint : FloatPoint(nodeRect.x() + nodeRect.width() - scaledViewportWidth, topLeftPoint.y()); + + if (newBlockHeight <= scaledViewportHeight) { + // The block fits in the viewport so center it. + d->m_finalBlockPoint = FloatPoint(anchor.x() - dx, anchor.y() - dy); + } else { + // The block is longer than the viewport so top align it and add 3 pixel margin. + d->m_finalBlockPoint = FloatPoint(anchor.x() - dx, anchor.y() - 3); + } + +#if ENABLE(VIEWPORT_REFLOW) + // We don't know how long the reflowed block will be so we position it at the top of the screen with a small margin. + if (settings()->textReflowMode() != WebSettings::TextReflowDisabled) { + d->m_finalBlockPoint = FloatPoint(anchor.x() - dx, anchor.y() - 3); + d->m_finalBlockPointReflowOffset = FloatPoint(-dx, -3); + } +#endif + + // Make sure that the original node rect is visible in the screen after the zoom. This is necessary because the identified block rect might + // not be the same as the original node rect, and it could force the original node rect off the screen. + FloatRect br(anchor, FloatSize(scaledViewportWidth, scaledViewportHeight)); + IntPoint clickPoint = d->mapFromTransformed(IntPoint(x, y)); + if (!br.contains(clickPoint)) { + d->m_finalBlockPointReflowOffset.move(0, (clickPoint.y() - scaledViewportHeight / 2) - d->m_finalBlockPoint.y()); + d->m_finalBlockPoint = FloatPoint(d->m_finalBlockPoint.x(), clickPoint.y() - scaledViewportHeight / 2); + } + + // Clamp the finalBlockPoint to not cause any overflow scrolling. + if (d->m_finalBlockPoint.x() < 0) { + d->m_finalBlockPoint.setX(0); + d->m_finalBlockPointReflowOffset.setX(0); + } else if (d->m_finalBlockPoint.x() + scaledViewportWidth > d->contentsSize().width()) { + d->m_finalBlockPoint.setX(d->contentsSize().width() - scaledViewportWidth); + d->m_finalBlockPointReflowOffset.setX(0); + } + + if (d->m_finalBlockPoint.y() < 0) { + d->m_finalBlockPoint.setY(0); + d->m_finalBlockPointReflowOffset.setY(0); + } else if (d->m_finalBlockPoint.y() + scaledViewportHeight > d->contentsSize().height()) { + d->m_finalBlockPoint.setY(d->contentsSize().height() - scaledViewportHeight); + d->m_finalBlockPointReflowOffset.setY(0); + } + + d->m_finalBlockPoint = d->mapToTransformedFloatPoint(d->m_finalBlockPoint); + + // Don't block zoom if the user is zooming and the new scale is only marginally different from the + // oldScale with only a marginal change in scroll position. Ignore scroll difference in the special case + // that the zoom level is the minimumScale. + if (!endOfBlockZoomMode && abs(newScale - oldScale) / oldScale < minimumExpandingRatio) { + const double minimumDisplacement = minimumExpandingRatio * d->transformedActualVisibleSize().width(); + if (oldScale == d->minimumScale() || (distanceBetweenPoints(roundTransformedPoint(d->mapToTransformed(d->scrollPosition())), roundTransformedPoint(d->m_finalBlockPoint)) < minimumDisplacement && abs(newScale - oldScale) / oldScale < 0.10)) { + if (isFirstZoom) { + d->resetBlockZoom(); + return false; + } + // Zoom out of block zoom. + blockZoom(x, y); + return true; + } + } + + d->m_blockZoomFinalScale = newScale; + + // We set this here to make sure we don't try to re-render the page at a different zoom level during loading. + d->m_userPerformedManualZoom = true; + d->m_userPerformedManualScroll = true; + d->m_client->animateBlockZoom(d->m_finalBlockPoint, d->m_blockZoomFinalScale); + + return true; +} + +bool WebPage::isMaxZoomed() const +{ + return (d->currentScale() == d->maximumScale()) || !d->isUserScalable(); +} + +bool WebPage::isMinZoomed() const +{ + return (d->currentScale() == d->minimumScale()) || !d->isUserScalable(); +} + +bool WebPage::isAtInitialZoom() const +{ + return (d->currentScale() == d->initialScale()) || !d->isUserScalable(); +} + +bool WebPagePrivate::shouldZoomOnEscape() const +{ + if (!isUserScalable()) + return false; + + // If the initial scale is not reachable, don't try to zoom. + if (initialScale() < minimumScale() || initialScale() > maximumScale()) + return false; + + // Don't ever zoom in when we press escape. + if (initialScale() >= currentScale()) + return false; + + return currentScale() != initialScale(); +} + +void WebPage::zoomToInitialScale() +{ + if (!d->isUserScalable()) + return; + + d->zoomAboutPoint(d->initialScale(), d->centerOfVisibleContentsRect()); +} + +bool WebPage::zoomToOneOne() +{ + if (!d->isUserScalable()) + return false; + + double scale = 1; + return d->zoomAboutPoint(scale, d->centerOfVisibleContentsRect()); +} + +Platform::IntRect WebPage::focusNodeRect() +{ + return d->focusNodeRect(); +} + +void WebPage::setFocused(bool focused) +{ + FocusController* focusController = d->m_page->focusController(); + focusController->setActive(focused); + if (focused) { + Frame* frame = focusController->focusedFrame(); + if (!frame) + focusController->setFocusedFrame(d->m_mainFrame); + } + focusController->setFocused(focused); +} + +bool WebPage::findNextString(const char* text, bool forward) +{ + return d->m_inPageSearchManager->findNextString(String::fromUTF8(text), forward); +} + +void WebPage::runLayoutTests() +{ +#if ENABLE_DRT + // FIXME: do we need API to toggle this? + d->m_page->settings()->setDeveloperExtrasEnabled(true); + + if (!d->m_dumpRenderTree) + d->m_dumpRenderTree = new DumpRenderTree(this); + d->m_dumpRenderTree->runTests(); +#endif +} + +bool WebPage::enableScriptDebugger() +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (d->m_scriptDebugger) + return true; + + d->m_scriptDebugger = adoptPtr(new JavaScriptDebuggerBlackBerry(this->d)); + + return !!d->m_scriptDebugger; +#endif +} + +bool WebPage::disableScriptDebugger() +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (!d->m_scriptDebugger) + return true; + + d->m_scriptDebugger.clear(); + return true; +#endif +} + +void WebPage::addBreakpoint(const unsigned short* url, unsigned urlLength, int lineNumber, const unsigned short* condition, unsigned conditionLength) +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (d->m_scriptDebugger) + d->m_scriptDebugger->addBreakpoint(url, urlLength, lineNumber, condition, conditionLength); +#endif +} + +void WebPage::updateBreakpoint(const unsigned short* url, unsigned urlLength, int lineNumber, const unsigned short* condition, unsigned conditionLength) +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (d->m_scriptDebugger) + d->m_scriptDebugger->updateBreakpoint(url, urlLength, lineNumber, condition, conditionLength); +#endif +} + +void WebPage::removeBreakpoint(const unsigned short* url, unsigned urlLength, int lineNumber) +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (d->m_scriptDebugger) + d->m_scriptDebugger->removeBreakpoint(url, urlLength, lineNumber); +#endif +} + +bool WebPage::pauseOnExceptions() +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + return d->m_scriptDebugger ? d->m_scriptDebugger->pauseOnExceptions() : false; +#endif +} + +void WebPage::setPauseOnExceptions(bool pause) +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (d->m_scriptDebugger) + d->m_scriptDebugger->setPauseOnExceptions(pause); +#endif +} + +void WebPage::pauseInDebugger() +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (d->m_scriptDebugger) + d->m_scriptDebugger->pauseInDebugger(); +#endif +} + +void WebPage::resumeDebugger() +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (d->m_scriptDebugger) + d->m_scriptDebugger->resumeDebugger(); +#endif +} + +void WebPage::stepOverStatementInDebugger() +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (d->m_scriptDebugger) + d->m_scriptDebugger->stepOverStatementInDebugger(); +#endif +} + +void WebPage::stepIntoStatementInDebugger() +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (d->m_scriptDebugger) + d->m_scriptDebugger->stepIntoStatementInDebugger(); +#endif +} + +void WebPage::stepOutOfFunctionInDebugger() +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (d->m_scriptDebugger) + d->m_scriptDebugger->stepOutOfFunctionInDebugger(); +#endif +} + +unsigned WebPage::timeoutForJavaScriptExecution() const +{ + return Settings::timeoutForJavaScriptExecution(d->m_page->groupName()); +} + +void WebPage::setTimeoutForJavaScriptExecution(unsigned ms) +{ + Settings::setTimeoutForJavaScriptExecution(d->m_page->groupName(), ms); + + Document* doc = d->m_page->mainFrame()->document(); + if (!doc) + return; + + doc->globalData()->timeoutChecker.setTimeoutInterval(ms); +} + +JSContextRef WebPage::scriptContext() const +{ + if (!d->m_mainFrame) + return 0; + + JSC::Bindings::RootObject *root = d->m_mainFrame->script()->bindingRootObject(); + if (!root) + return 0; + + JSC::ExecState *exec = root->globalObject()->globalExec(); + return toRef(exec); +} + +JSValueRef WebPage::windowObject() const +{ + return toRef(d->m_mainFrame->script()->globalObject(mainThreadNormalWorld())); +} + +// Serialize only the members of HistoryItem which are needed by the client, +// and copy them into a SharedArray. Also include the HistoryItem pointer which +// will be used by the client as an opaque reference to identify the item. +void WebPage::getBackForwardList(SharedArray<BackForwardEntry>& result, unsigned int& resultSize) const +{ + HistoryItemVector entries = static_cast<BackForwardListImpl*>(d->m_page->backForward()->client())->entries(); + resultSize = entries.size(); + result.reset(new BackForwardEntry[resultSize]); + + for (unsigned i = 0; i < resultSize; ++i) { + RefPtr<HistoryItem> entry = entries[i]; + BackForwardEntry& resultEntry = result[i]; + resultEntry.url = entry->urlString(); + resultEntry.originalUrl = entry->originalURLString(); + resultEntry.title = entry->title(); + resultEntry.networkToken = entry->viewState().networkToken; + resultEntry.lastVisitWasHTTPNonGet = entry->lastVisitWasHTTPNonGet(); + resultEntry.id = backForwardIdFromHistoryItem(entry.get()); + + // Make sure the HistoryItem is not disposed while the result list is still being used, to make sure the pointer is not reused + // will be balanced by deref in releaseBackForwardEntry. + entry->ref(); + } +} + +void WebPage::releaseBackForwardEntry(BackForwardId id) const +{ + HistoryItem* item = historyItemFromBackForwardId(id); + ASSERT(item); + item->deref(); +} + +void WebPage::clearBrowsingData() +{ + clearMemoryCaches(); + clearAppCache(d->m_page->groupName()); + clearLocalStorage(); + clearCookieCache(); + clearHistory(); + clearPluginSiteData(); +} + +void WebPage::clearHistory() +{ + // Don't clear the back-forward list as we might like to keep it. +} + +void WebPage::clearCookies() +{ + clearCookieCache(); +} + +void WebPage::clearLocalStorage() +{ + BlackBerry::WebKit::clearLocalStorage(d->m_page->groupName()); + clearDatabase(d->m_page->groupName()); +} + +void WebPage::clearCache() +{ + clearMemoryCaches(); + clearAppCache(d->m_page->groupName()); +} + +void WebPage::clearBackForwardList(bool keepCurrentPage) const +{ + BackForwardListImpl* backForwardList = static_cast<BackForwardListImpl*>(d->m_page->backForward()->client()); + RefPtr<HistoryItem> currentItem = backForwardList->currentItem(); + while (!backForwardList->entries().isEmpty()) + backForwardList->removeItem(backForwardList->entries().last().get()); + if (keepCurrentPage) + backForwardList->addItem(currentItem); +} + +bool WebPage::isEnableLocalAccessToAllCookies() const +{ + return cookieManager().canLocalAccessAllCookies(); +} + +void WebPage::setEnableLocalAccessToAllCookies(bool enabled) +{ + cookieManager().setCanLocalAccessAllCookies(enabled); +} + +void WebPage::addVisitedLink(const unsigned short* url, unsigned int length) +{ + ASSERT(d->m_page); + d->m_page->group().addVisitedLink(url, length); +} + +#if ENABLE(WEBDOM) +WebDOMDocument WebPage::document() const +{ + if (!d->m_mainFrame) + return WebDOMDocument(); + return WebDOMDocument(d->m_mainFrame->document()); +} + +WebDOMNode WebPage::nodeAtPoint(int x, int y) +{ + HitTestResult result = d->m_mainFrame->eventHandler()->hitTestResultAtPoint(d->mapFromTransformed(IntPoint(x, y)), false); + Node* node = result.innerNonSharedNode(); + return WebDOMNode(node); +} + +bool WebPage::getNodeRect(const WebDOMNode& node, Platform::IntRect& result) +{ + Node* nodeImpl = node.impl(); + if (nodeImpl && nodeImpl->renderer()) { + result = nodeImpl->getRect(); + return true; + } + + return false; +} + +bool WebPage::setNodeFocus(const WebDOMNode& node, bool on) +{ + Node* nodeImpl = node.impl(); + + if (nodeImpl && nodeImpl->isFocusable()) { + Document* doc = nodeImpl->document(); + if (Page* page = doc->page()) { + // Modify if focusing on node or turning off focused node. + if (on) { + page->focusController()->setFocusedNode(nodeImpl, doc->frame()); + if (nodeImpl->isElementNode()) + static_cast<Element*>(nodeImpl)->updateFocusAppearance(true); + d->m_inputHandler->didNodeOpenPopup(nodeImpl); + } else if (doc->focusedNode() == nodeImpl) // && !on + page->focusController()->setFocusedNode(0, doc->frame()); + + return true; + } + } + return false; +} + +bool WebPage::setNodeHovered(const WebDOMNode& node, bool on) +{ + if (Node* nodeImpl = node.impl()) { + nodeImpl->setHovered(on); + return true; + } + return false; +} + +bool WebPage::nodeHasHover(const WebDOMNode& node) +{ + if (Node* nodeImpl = node.impl()) { + if (RenderStyle* style = nodeImpl->renderStyle()) + return style->affectedByHoverRules(); + } + return false; +} +#endif + +String WebPagePrivate::findPatternStringForUrl(const KURL& url) const +{ + if ((m_webSettings->shouldHandlePatternUrls() && protocolIs(url, "pattern")) + || protocolIs(url, "tel") + || protocolIs(url, "wtai") + || protocolIs(url, "cti") + || protocolIs(url, "mailto") + || protocolIs(url, "sms") + || protocolIs(url, "pin")) { + return url; + } + return String(); +} + +bool WebPage::defersLoading() const +{ + return d->m_page->defersLoading(); +} + +bool WebPage::willFireTimer() +{ + if (d->isLoading()) + return true; + + return d->m_backingStore->d->willFireTimer(); +} + +void WebPage::notifyPagePause() +{ + FOR_EACH_PLUGINVIEW(d->m_pluginViews) + (*it)->handlePauseEvent(); +} + +void WebPage::notifyPageResume() +{ + FOR_EACH_PLUGINVIEW(d->m_pluginViews) + (*it)->handleResumeEvent(); +} + +void WebPage::notifyPageBackground() +{ +#if USE(ACCELERATED_COMPOSITING) + d->suspendRootLayerCommit(); +#endif + + FOR_EACH_PLUGINVIEW(d->m_pluginViews) + (*it)->handleBackgroundEvent(); +} + +void WebPage::notifyPageForeground() +{ +#if USE(ACCELERATED_COMPOSITING) + d->resumeRootLayerCommit(); +#endif + + FOR_EACH_PLUGINVIEW(d->m_pluginViews) + (*it)->handleForegroundEvent(); +} + +void WebPage::notifyPageFullScreenAllowed() +{ + FOR_EACH_PLUGINVIEW(d->m_pluginViews) + (*it)->handleFullScreenAllowedEvent(); +} + +void WebPage::notifyPageFullScreenExit() +{ + FOR_EACH_PLUGINVIEW(d->m_pluginViews) + (*it)->handleFullScreenExitEvent(); +} + +void WebPage::notifyDeviceIdleStateChange(bool enterIdle) +{ + FOR_EACH_PLUGINVIEW(d->m_pluginViews) + (*it)->handleIdleEvent(enterIdle); +} + +void WebPage::notifyAppActivationStateChange(ActivationStateType activationState) +{ +#if ENABLE(VIDEO) + MediaPlayerPrivate::notifyAppActivatedEvent(activationState == ActivationActive); +#endif + + FOR_EACH_PLUGINVIEW(d->m_pluginViews) { + switch (activationState) { + case ActivationActive: + (*it)->handleAppActivatedEvent(); + break; + case ActivationInactive: + (*it)->handleAppDeactivatedEvent(); + break; + case ActivationStandby: + (*it)->handleAppStandbyEvent(); + break; + default: // FIXME: Get rid of the default to force a compiler error instead of using a runtime error. See PR #121109. + ASSERT_NOT_REACHED(); + break; + } + } +} + +void WebPage::notifySwipeEvent() +{ + FOR_EACH_PLUGINVIEW(d->m_pluginViews) + (*it)->handleSwipeEvent(); +} + +void WebPage::notifyScreenPowerStateChanged(bool powered) +{ + FOR_EACH_PLUGINVIEW(d->m_pluginViews) + (*it)->handleScreenPowerEvent(powered); +} + +void WebPage::notifyFullScreenVideoExited(bool done) +{ + UNUSED_PARAM(done); +#if ENABLE(VIDEO) + if (HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(d->m_fullscreenVideoNode.get())) + mediaElement->exitFullscreen(); +#endif +} + +void WebPage::clearPluginSiteData() +{ + PluginDatabase* database = PluginDatabase::installedPlugins(true); + + if (!database) + return; + + Vector<PluginPackage*> plugins = database->plugins(); + + Vector<PluginPackage*>::const_iterator end = plugins.end(); + for (Vector<PluginPackage*>::const_iterator it = plugins.begin(); it != end; ++it) + (*it)->clearSiteData(String()); +} + +void WebPage::onInputLocaleChanged(bool isRTL) +{ + d->onInputLocaleChanged(isRTL); +} + +void WebPage::onNetworkAvailabilityChanged(bool available) +{ + updateOnlineStatus(available); +} + +void WebPage::onCertificateStoreLocationSet(const WebString& caPath) +{ +#if ENABLE(VIDEO) + MediaPlayerPrivate::setCertificatePath(caPath); +#endif +} + +void WebPage::enableWebInspector() +{ + d->m_page->inspectorController()->connectFrontend(); + d->m_page->settings()->setDeveloperExtrasEnabled(true); +} + +void WebPage::disableWebInspector() +{ + d->m_page->inspectorController()->disconnectFrontend(); + d->m_page->settings()->setDeveloperExtrasEnabled(false); +} + +void WebPage::enablePasswordEcho() +{ + d->m_page->settings()->setPasswordEchoEnabled(true); +} + +void WebPage::disablePasswordEcho() +{ + d->m_page->settings()->setPasswordEchoEnabled(false); +} + +void WebPage::dispatchInspectorMessage(const char* message, int length) +{ + String stringMessage(message, length); + d->m_page->inspectorController()->dispatchMessageFromFrontend(stringMessage); +} + +Frame* WebPage::mainFrame() const +{ + return d->m_mainFrame; +} + +#if USE(ACCELERATED_COMPOSITING) +void WebPagePrivate::drawLayersOnCommit() +{ + if (!Platform::userInterfaceThreadMessageClient()->isCurrentThread()) { + // This method will only be called when the layer appearance changed due to + // animations. And only if we don't need a one shot drawing sync. + ASSERT(!needsOneShotDrawingSynchronization()); + + if (!m_webPage->isVisible() || !m_backingStore->d->isActive()) + return; + + m_backingStore->d->willDrawLayersOnCommit(); + + Platform::userInterfaceThreadMessageClient()->dispatchMessage( + Platform::createMethodCallMessage(&WebPagePrivate::drawLayersOnCommit, this)); + return; + } + + if (m_client->window()->windowUsage() == Platform::Graphics::Window::GLES2Usage) { + m_backingStore->d->blitVisibleContents(); + return; // blitVisibleContents() includes drawSubLayers() in this case. + } + + if (!drawSubLayers()) + return; + + // If we use the compositing surface, we need to re-blit the + // backingstore and blend the compositing surface on top of that + // in order to get the newly drawn layers on screen. + if (!SurfacePool::globalSurfacePool()->compositingSurface()) + return; + + // If there are no visible layers, return early. + if (lastCompositingResults().isEmpty() && lastCompositingResults().wasEmpty) + return; + + if (m_backingStore->d->shouldDirectRenderingToWindow()) + return; + + m_backingStore->d->blitVisibleContents(); +} + +bool WebPagePrivate::drawSubLayers(const IntRect& dstRect, const FloatRect& contents) +{ + ASSERT(Platform::userInterfaceThreadMessageClient()->isCurrentThread()); + if (!Platform::userInterfaceThreadMessageClient()->isCurrentThread()) + return false; + + if (m_compositor) { + m_compositor->setCompositingOntoMainWindow( + m_client->window()->windowUsage() == Platform::Graphics::Window::GLES2Usage); + return m_compositor->drawLayers(dstRect, contents); + } + + return false; +} + +bool WebPagePrivate::drawSubLayers() +{ + ASSERT(Platform::userInterfaceThreadMessageClient()->isCurrentThread()); + if (!Platform::userInterfaceThreadMessageClient()->isCurrentThread()) + return false; + + return m_backingStore->d->drawSubLayers(); +} + +void WebPagePrivate::scheduleRootLayerCommit() +{ + if (!m_frameLayers || !m_frameLayers->hasLayer()) + return; + + m_needsCommit = true; + if (!m_rootLayerCommitTimer->isActive()) + m_rootLayerCommitTimer->startOneShot(0); +} + +static bool needsLayoutRecursive(FrameView* view) +{ + if (view->needsLayout()) + return true; + + bool subframesNeedsLayout = false; + const HashSet<RefPtr<Widget> >* viewChildren = view->children(); + HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end(); + for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end && !subframesNeedsLayout; ++current) { + Widget* widget = (*current).get(); + if (widget->isFrameView()) + subframesNeedsLayout |= needsLayoutRecursive(static_cast<FrameView*>(widget)); + } + + return subframesNeedsLayout; +} + +LayerRenderingResults WebPagePrivate::lastCompositingResults() const +{ + if (m_compositor) + return m_compositor->lastCompositingResults(); + return LayerRenderingResults(); +} + +void WebPagePrivate::commitRootLayer(const IntRect& layoutRectForCompositing, + const IntSize& contentsSizeForCompositing) +{ + if (!m_frameLayers || !m_compositor) + return; + + m_compositor->setLayoutRectForCompositing(layoutRectForCompositing); + m_compositor->setContentsSizeForCompositing(contentsSizeForCompositing); + m_compositor->commit(m_frameLayers->rootLayer()); +} + +bool WebPagePrivate::commitRootLayerIfNeeded() +{ + if (m_suspendRootLayerCommit) + return false; + + if (!m_needsCommit) + return false; + + if (!m_frameLayers || !m_frameLayers->hasLayer()) + return false; + + FrameView* view = m_mainFrame->view(); + if (!view) + return false; + + // If we sync compositing layers when a layout is pending, we may cause painting of compositing + // layer content to occur before layout has happened, which will cause paintContents() to bail. + if (needsLayoutRecursive(view)) { + // In case of one shot drawing synchronization, you + // should first layoutIfNeeded, render, then commit and draw the layers. + ASSERT(!needsOneShotDrawingSynchronization()); + return false; + } + + m_needsCommit = false; + // We get here either due to the commit timer, which would have called + // render if a one shot sync was needed. Or we get called from render + // before the timer times out, which means we are doing a one shot anyway. + m_needsOneShotDrawingSynchronization = false; + + if (m_rootLayerCommitTimer->isActive()) + m_rootLayerCommitTimer->stop(); + + m_frameLayers->commitOnWebKitThread(currentScale()); + updateDelegatedOverlays(); + + // Stash the visible content rect according to webkit thread + // This is the rectangle used to layout fixed positioned elements, + // and that's what the layer renderer wants. + IntRect layoutRectForCompositing(scrollPosition(), actualVisibleSize()); + IntSize contentsSizeForCompositing = contentsSize(); + + // Commit changes made to the layers synchronously with the compositing thread. + Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage( + Platform::createMethodCallMessage( + &WebPagePrivate::commitRootLayer, + this, + layoutRectForCompositing, + contentsSizeForCompositing)); + + return true; +} + +void WebPagePrivate::rootLayerCommitTimerFired(Timer<WebPagePrivate>*) +{ + if (m_suspendRootLayerCommit) + return; + + // The commit timer may have fired just before the layout timer, or for some + // other reason we need layout. It's not allowed to commit when a layout is + // pending, becaues a commit can cause parts of the web page to be rendered + // to texture. + // The layout can also turn of compositing altogether, so we need to be prepared + // to handle a one shot drawing synchronization after the layout. + requestLayoutIfNeeded(); + + bool isSingleTargetWindow = SurfacePool::globalSurfacePool()->compositingSurface() + || m_client->window()->windowUsage() == Platform::Graphics::Window::GLES2Usage; + + // If we are doing direct rendering and have a single rendering target, + // committing is equivalent to a one shot drawing synchronization. + // We need to re-render the web page, re-render the layers, and + // then blit them on top of the re-rendered web page. + if (isSingleTargetWindow && m_backingStore->d->shouldDirectRenderingToWindow()) + setNeedsOneShotDrawingSynchronization(); + + if (needsOneShotDrawingSynchronization()) { + const IntRect windowRect = IntRect(IntPoint::zero(), viewportSize()); + m_backingStore->d->repaint(windowRect, true /*contentChanged*/, true /*immediate*/); + return; + } + + // If the web page needs layout, the commit will fail. + // No need to draw the layers if nothing changed. + if (commitRootLayerIfNeeded()) + drawLayersOnCommit(); +} + +void WebPagePrivate::setIsAcceleratedCompositingActive(bool active) +{ + // Backing store can be null here because it happens during teardown. + if (m_isAcceleratedCompositingActive == active || !m_backingStore) + return; + + m_isAcceleratedCompositingActive = active; + + if (!active) { + m_compositor.clear(); + resetCompositingSurface(); + return; + } + + if (!m_compositor) { + m_compositor = adoptPtr(new WebPageCompositor(this)); + m_isAcceleratedCompositingActive = m_compositor->hardwareCompositing(); + if (!m_isAcceleratedCompositingActive) + m_compositor.clear(); + } +} + +void WebPagePrivate::resetCompositingSurface() +{ + if (!Platform::userInterfaceThreadMessageClient()->isCurrentThread()) { + Platform::userInterfaceThreadMessageClient()->dispatchMessage( + Platform::createMethodCallMessage( + &WebPagePrivate::resetCompositingSurface, this)); + return; + } + + if (m_compositor) + m_compositor->setLastCompositingResults(LayerRenderingResults()); +} + +void WebPagePrivate::setRootLayerWebKitThread(Frame* frame, LayerWebKitThread* layer) +{ + // This method updates the FrameLayers based on input from WebCore. + // FrameLayers keeps track of the layer proxies attached to frames. + // We will have to compute a new root layer and update the compositor. + if (!layer && !m_frameLayers) + return; + + if (!layer) { + ASSERT(m_frameLayers); + m_frameLayers->removeLayerByFrame(frame); + if (!m_frameLayers->hasLayer()) + m_frameLayers.clear(); + } else { + if (!m_frameLayers) + m_frameLayers = adoptPtr(new FrameLayers(this)); + + if (!m_frameLayers->containsLayerForFrame(frame)) + m_frameLayers->addLayer(frame, layer); + + ASSERT(m_frameLayers); + } + + LayerCompositingThread* rootLayerCompositingThread = 0; + if (m_frameLayers && m_frameLayers->rootLayer()) + rootLayerCompositingThread = m_frameLayers->rootLayer()->layerCompositingThread(); + + setRootLayerCompositingThread(rootLayerCompositingThread); +} + +void WebPagePrivate::setRootLayerCompositingThread(LayerCompositingThread* layer) +{ + if (!Platform::userInterfaceThreadMessageClient()->isCurrentThread()) { + Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage( + Platform::createMethodCallMessage(&WebPagePrivate::setRootLayerCompositingThread, this, layer)); + return; + } + + // Depending on whether we have a root layer or not, + // this method will turn on or off accelerated compositing. + if (!layer) { + // Don't ASSERT(m_compositor) here because we may be called in + // the process of destruction of WebPage where we have already + // called syncDestroyCompositorOnCompositingThread() to destroy + // the compositor. + setIsAcceleratedCompositingActive(false); + return; + } + + if (!m_compositor) + setIsAcceleratedCompositingActive(true); + + // Don't ASSERT(m_compositor) here because setIsAcceleratedCompositingActive(true) + // may not turn accelerated compositing on since m_backingStore is 0. + if (m_compositor) + m_compositor->setRootLayer(layer); +} + +void WebPagePrivate::destroyCompositor() +{ + m_compositor.clear(); +} + +void WebPagePrivate::syncDestroyCompositorOnCompositingThread() +{ + if (!m_compositor) + return; + + Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage( + Platform::createMethodCallMessage( + &WebPagePrivate::destroyCompositor, this)); +} + +void WebPagePrivate::destroyLayerResources() +{ + m_compositor->releaseLayerResources(); +} + +void WebPagePrivate::suspendRootLayerCommit() +{ + if (m_suspendRootLayerCommit) + return; + + m_suspendRootLayerCommit = true; + + if (!m_frameLayers || !m_frameLayers->hasLayer() || !m_compositor) + return; + + Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage( + Platform::createMethodCallMessage(&WebPagePrivate::destroyLayerResources, this)); +} + +void WebPagePrivate::resumeRootLayerCommit() +{ + if (!m_suspendRootLayerCommit) + return; + + m_suspendRootLayerCommit = false; + m_needsCommit = true; + + // Recreate layer resources if needed. + commitRootLayerIfNeeded(); +} + +bool WebPagePrivate::needsOneShotDrawingSynchronization() +{ + return m_needsOneShotDrawingSynchronization; +} + +void WebPagePrivate::setNeedsOneShotDrawingSynchronization() +{ + // This means we have to commit layers on next render, or render on the next commit, + // whichever happens first. + m_needsCommit = true; + m_needsOneShotDrawingSynchronization = true; +} +#endif // USE(ACCELERATED_COMPOSITING) + +void WebPagePrivate::enterFullscreenForNode(Node* node) +{ +#if ENABLE(VIDEO) + if (!node || !node->hasTagName(HTMLNames::videoTag)) + return; + + MediaPlayer* player = static_cast<HTMLMediaElement*>(node)->player(); + if (!player) + return; + + MediaPlayerPrivate* mmrPlayer = static_cast<MediaPlayerPrivate*>(player->implementation()); + if (!mmrPlayer) + return; + + Platform::Graphics::Window* window = mmrPlayer->windowGet(); + if (!window) + return; + + unsigned x, y, width, height; + mmrPlayer->windowPositionGet(x, y, width, height); + + const char* contextName = mmrPlayer->mmrContextNameGet(); + if (!contextName) + return; + + mmrPlayer->setFullscreenWebPageClient(m_client); + m_fullscreenVideoNode = node; + m_client->fullscreenStart(contextName, window, x, y, width, height); +#endif +} + +void WebPagePrivate::exitFullscreenForNode(Node* node) +{ +#if ENABLE(VIDEO) + if (m_fullscreenVideoNode.get()) { + m_client->fullscreenStop(); + m_fullscreenVideoNode = 0; + } + + if (!node || !node->hasTagName(HTMLNames::videoTag)) + return; + + MediaPlayer* player = static_cast<HTMLMediaElement*>(node)->player(); + if (!player) + return; + + MediaPlayerPrivate* mmrPlayer = static_cast<MediaPlayerPrivate*>(player->implementation()); + if (!mmrPlayer) + return; + + // Fullscreen mode is being turned off, so MediaPlayerPrivate no longer needs the pointer. + mmrPlayer->setFullscreenWebPageClient(0); +#endif +} + +void WebPagePrivate::didChangeSettings(WebSettings* webSettings) +{ + Settings* coreSettings = m_page->settings(); + m_page->setGroupName(webSettings->pageGroupName()); + coreSettings->setXSSAuditorEnabled(webSettings->xssAuditorEnabled()); + coreSettings->setLoadsImagesAutomatically(webSettings->loadsImagesAutomatically()); + coreSettings->setShouldDrawBorderWhileLoadingImages(webSettings->shouldDrawBorderWhileLoadingImages()); + coreSettings->setScriptEnabled(webSettings->isJavaScriptEnabled()); + coreSettings->setPrivateBrowsingEnabled(webSettings->isPrivateBrowsingEnabled()); + coreSettings->setDefaultFixedFontSize(webSettings->defaultFixedFontSize()); + coreSettings->setDefaultFontSize(webSettings->defaultFontSize()); + coreSettings->setMinimumFontSize(webSettings->minimumFontSize()); + coreSettings->setSerifFontFamily(webSettings->serifFontFamily().impl()); + coreSettings->setFixedFontFamily(webSettings->fixedFontFamily().impl()); + coreSettings->setSansSerifFontFamily(webSettings->sansSerifFontFamily().impl()); + coreSettings->setStandardFontFamily(webSettings->standardFontFamily().impl()); + coreSettings->setJavaScriptCanOpenWindowsAutomatically(webSettings->canJavaScriptOpenWindowsAutomatically()); + coreSettings->setAllowScriptsToCloseWindows(webSettings->canJavaScriptOpenWindowsAutomatically()); // Why are we using the same value as setJavaScriptCanOpenWindowsAutomatically()? + coreSettings->setPluginsEnabled(webSettings->arePluginsEnabled()); + coreSettings->setDefaultTextEncodingName(webSettings->defaultTextEncodingName().impl()); + coreSettings->setDownloadableBinaryFontsEnabled(webSettings->downloadableBinaryFontsEnabled()); + coreSettings->setSpatialNavigationEnabled(m_webSettings->isSpatialNavigationEnabled()); + + // UserScalable should be reset by new settings. + setUserScalable(webSettings->isUserScalable()); + + WebString stylesheetURL = webSettings->userStyleSheetString(); + if (stylesheetURL.isEmpty()) + stylesheetURL = webSettings->userStyleSheetLocation(); + if (!stylesheetURL.isEmpty()) + coreSettings->setUserStyleSheetLocation(KURL(KURL(), stylesheetURL)); + + coreSettings->setFirstScheduledLayoutDelay(webSettings->firstScheduledLayoutDelay()); + coreSettings->setUseCache(webSettings->useWebKitCache()); + +#if ENABLE(SQL_DATABASE) + // DatabaseTracker can only be initialized for once, so it doesn't + // make sense to change database path after DatabaseTracker has + // already been initialized. + static bool dbinit = false; + if (!dbinit && !webSettings->databasePath().isEmpty()) { + dbinit = true; + DatabaseTracker::initializeTracker(webSettings->databasePath()); + } + + // The directory of cacheStorage for one page group can only be initialized once. + static bool acinit = false; + if (!acinit && !webSettings->appCachePath().isEmpty()) { + acinit = true; + cacheStorage().setCacheDirectory(webSettings->appCachePath()); + } + + coreSettings->setLocalStorageDatabasePath(webSettings->localStoragePath()); + Database::setIsAvailable(webSettings->isDatabasesEnabled()); + DatabaseSync::setIsAvailable(webSettings->isDatabasesEnabled()); + + coreSettings->setLocalStorageEnabled(webSettings->isLocalStorageEnabled()); + coreSettings->setOfflineWebApplicationCacheEnabled(webSettings->isAppCacheEnabled()); + + m_page->group().groupSettings()->setLocalStorageQuotaBytes(webSettings->localStorageQuota()); + coreSettings->setUsesPageCache(webSettings->maximumPagesInCache()); + coreSettings->setFrameFlatteningEnabled(webSettings->isFrameFlatteningEnabled()); +#endif + +#if ENABLE(WEB_SOCKETS) + WebSocket::setIsAvailable(webSettings->areWebSocketsEnabled()); +#endif + +#if ENABLE(VIEWPORT_REFLOW) + coreSettings->setTextReflowEnabled(webSettings->textReflowMode() == WebSettings::TextReflowEnabled); +#endif + + // FIXME: We don't want HTMLTokenizer to yield for anything other than email case because + // call to currentTime() is too expensive on our platform. See RIM Bug #746. + coreSettings->setShouldUseFirstScheduledLayoutDelay(webSettings->isEmailMode()); + coreSettings->setProcessHTTPEquiv(!webSettings->isEmailMode()); + + coreSettings->setShouldUseCrossOriginProtocolCheck(!webSettings->allowCrossSiteRequests()); + + cookieManager().setPrivateMode(webSettings->isPrivateBrowsingEnabled()); + + if (m_mainFrame && m_mainFrame->view()) { + Color backgroundColor(webSettings->backgroundColor()); + m_mainFrame->view()->updateBackgroundRecursively(backgroundColor, backgroundColor.hasAlpha()); + } +} + +IntSize WebPagePrivate::defaultMaxLayoutSize() +{ + static IntSize size; + if (size.isEmpty()) + size = IntSize(std::max(1024, Platform::Graphics::Screen::landscapeWidth()), + std::max(768, Platform::Graphics::Screen::landscapeHeight())); + + return size; +} + +WebString WebPage::textHasAttribute(const WebString& query) const +{ + if (Document* doc = d->m_page->focusController()->focusedOrMainFrame()->document()) + return doc->queryCommandValue(query); + + return ""; +} + +void WebPage::setJavaScriptCanAccessClipboard(bool enabled) +{ + d->m_page->settings()->setJavaScriptCanAccessClipboard(enabled); +} + +#if USE(ACCELERATED_COMPOSITING) +void WebPagePrivate::blitVisibleContents() +{ + if (m_backingStore->d->shouldDirectRenderingToWindow()) + return; + + m_backingStore->d->blitVisibleContents(); +} +#endif + +void WebPage::setWebGLEnabled(bool enabled) +{ + if (!Platform::ITPolicy::isWebGLEnabled()) { + d->m_page->settings()->setWebGLEnabled(false); + return; + } + d->m_page->settings()->setWebGLEnabled(enabled); +} + +bool WebPage::isWebGLEnabled() const +{ + return d->m_page->settings()->webGLEnabled(); +} + +void WebPagePrivate::setNeedTouchEvents(bool value) +{ + m_needTouchEvents = value; +} + +} +} diff --git a/Source/WebKit/blackberry/Api/WebPage.h b/Source/WebKit/blackberry/Api/WebPage.h new file mode 100644 index 000000000..489f4536c --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebPage.h @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef WebPage_h +#define WebPage_h + +#include "ActiveNodeContext.h" +#include "BlackBerryGlobal.h" +#include <BlackBerryPlatformGuardedPointer.h> +#include <BlackBerryPlatformInputEvents.h> +#include <imf/input_data.h> +#include <network/NetworkRequest.h> + +struct OpaqueJSContext; +typedef const struct OpaqueJSContext* JSContextRef; + +struct OpaqueJSValue; +typedef const struct OpaqueJSValue* JSValueRef; + +namespace WebCore { +class ChromeClientBlackBerry; +class EditorClientBlackBerry; +class Element; +class Frame; +class FrameLoaderClientBlackBerry; +class GeolocationControllerClientBlackBerry; +class IconDatabaseClientBlackBerry; +class InspectorClientBlackBerry; +class JavaScriptDebuggerBlackBerry; +class Node; +class RenderObject; +class VisibleSelection; +} + +class WebDOMDocument; +class WebDOMNode; +template<typename T> class SharedArray; + +namespace BlackBerry { +namespace Platform { +class IntPoint; +class IntRect; +class IntSize; +class KeyboardEvent; +class MouseEvent; +class TouchEvent; +class TouchPoint; +} + +namespace WebKit { + +class BackingStore; +class BackingStoreClient; +class BackingStorePrivate; +class DumpRenderTreeClient; +class RenderQueue; +class WebPageClient; +class WebPageGroupLoadDeferrer; +class WebPagePrivate; +class WebSettings; + +enum JavaScriptDataType { JSUndefined = 0, JSNull, JSBoolean, JSNumber, JSString, JSObject, JSException, JSDataTypeMax }; + +enum ActivationStateType { ActivationActive, ActivationInactive, ActivationStandby }; + +enum TargetDetectionStrategy {PointBased, RectBased}; + +class BLACKBERRY_EXPORT WebPage : public Platform::GuardedPointerBase { +public: + WebPage(WebPageClient*, const WebString& pageGroupName, const Platform::IntRect&); + void destroy(); + + WebPageClient* client() const; + + void load(const char* url, const char* networkToken, bool isInitial = false); + + void loadExtended(const char* url, const char* networkToken, const char* method, Platform::NetworkRequest::CachePolicy = Platform::NetworkRequest::UseProtocolCachePolicy, const char* data = 0, size_t dataLength = 0, const char* const* headers = 0, size_t headersLength = 0, bool mustHandleInternally = false); + + void loadFile(const char* path, const char* overrideContentType = ""); + + void loadString(const char* string, const char* baseURL, const char* contentType = "text/html", const char* failingURL = 0); + + void download(const Platform::NetworkRequest&); + + bool executeJavaScript(const char* script, JavaScriptDataType& returnType, WebString& returnValue); + + // This will execute the script even if in-page JavaScript is disabled. + bool executeJavaScriptInIsolatedWorld(const char* script, JavaScriptDataType& returnType, WebString& returnValue); + + // Takes a UTF16 encoded script that is used explicitly by the pattern matching code + bool executeJavaScriptInIsolatedWorld(const std::wstring& script, JavaScriptDataType& returnType, WebString& returnValue); + + void initializeIconDataBase(); + + void stopLoading(); + + // This will force any unload handlers to run. + void prepareToDestroy(); + + void reload(); + void reloadFromCache(); + + WebSettings* settings() const; + + void setVisible(bool); + bool isVisible() const; + + void setScreenOrientation(int); + void applyPendingOrientationIfNeeded(); + + Platform::IntSize viewportSize() const; + void setViewportSize(const Platform::IntSize& viewportSize, bool ensureFocusElementVisible = true); + + void resetVirtualViewportOnCommitted(bool reset); + void setVirtualViewportSize(int width, int height); + + // Used for default layout size unless overridden by web content or by other APIs. + void setDefaultLayoutSize(int width, int height); + + bool mouseEvent(const Platform::MouseEvent&, bool* wheelDeltaAccepted = 0); + + // Handles native javascript touch events. + bool touchEvent(const Platform::TouchEvent&); + + // For conversion to mouse events. + void touchEventCancel(); + void touchEventCancelAndClearFocusedNode(); + bool touchPointAsMouseEvent(const Platform::TouchPoint&); + + // Returns true if the key stroke was handled by WebKit. + bool keyEvent(const Platform::KeyboardEvent&); + + WebString title() const; + WebString selectedText() const; + WebString cutSelectedText(); + void insertText(const WebString&); + void clearCurrentInputField(); + + void cut(); + void copy(); + void paste(); + + // Text encoding. + WebString textEncoding(); + WebString forcedTextEncoding(); + void setForcedTextEncoding(const char*); + + // Scroll position returned is in transformed coordinates. + Platform::IntPoint scrollPosition() const; + // Scroll position provided should be in transformed coordinates. + void setScrollPosition(const Platform::IntPoint&); + bool scrollBy(const Platform::IntSize&, bool scrollMainFrame = true); + void notifyInRegionScrollStatusChanged(bool status); + void setScrollOriginPoint(const Platform::IntPoint&); + + BackingStore* backingStore() const; + + bool zoomToFit(); + bool zoomToOneOne(); + void zoomToInitialScale(); + bool blockZoom(int x, int y); + void blockZoomAnimationFinished(); + bool isAtInitialZoom() const; + bool isMaxZoomed() const; + bool isMinZoomed() const; + bool pinchZoomAboutPoint(double scale, int x, int y); + + bool isUserScalable() const; + double currentScale() const; + double initialScale() const; + double zoomToFitScale() const; + void setInitialScale(double); + double minimumScale() const; + void setMinimumScale(double); + double maximumScale() const; + void setMaximumScale(double); + + void assignFocus(Platform::FocusDirection); + + Platform::IntRect focusNodeRect(); + + void setFocused(bool); + + void clearBrowsingData(); + void clearHistory(); + void clearCookies(); + void clearCache(); + void clearLocalStorage(); + + void runLayoutTests(); + + // Finds and selects the next utf8 string that is a case sensitive + // match in the web page. It will wrap the web page if it reaches + // the end. An empty string will result in no match and no selection. + // Returns true if the string matched and false if not. + bool findNextString(const char*, bool forward = true); + + // JavaScriptDebugger interface. + bool enableScriptDebugger(); + bool disableScriptDebugger(); + + JSContextRef scriptContext() const; + JSValueRef windowObject() const; + + void addBreakpoint(const unsigned short* url, unsigned urlLength, int lineNumber, const unsigned short* condition, unsigned conditionLength); + void updateBreakpoint(const unsigned short* url, unsigned urlLength, int lineNumber, const unsigned short* condition, unsigned conditionLength); + void removeBreakpoint(const unsigned short* url, unsigned urlLength, int lineNumber); + + bool pauseOnExceptions(); + void setPauseOnExceptions(bool); + + void pauseInDebugger(); + void resumeDebugger(); + + void stepOverStatementInDebugger(); + void stepIntoStatementInDebugger(); + void stepOutOfFunctionInDebugger(); + + unsigned timeoutForJavaScriptExecution() const; + void setTimeoutForJavaScriptExecution(unsigned ms); + + void setCaretHighlightStyle(Platform::CaretHighlightStyle); + + // IMF functions. + bool setBatchEditingActive(bool); + bool setInputSelection(unsigned start, unsigned end); + int inputCaretPosition() const; + bool deleteTextRelativeToCursor(unsigned leftOffset, unsigned rightOffset); + spannable_string_t* selectedText(int32_t flags); + spannable_string_t* textBeforeCursor(int32_t length, int32_t flags); + spannable_string_t* textAfterCursor(int32_t length, int32_t flags); + extracted_text_t* extractedTextRequest(extracted_text_request_t*, int32_t flags); + int32_t setComposingRegion(int32_t start, int32_t end); + int32_t finishComposition(); + int32_t setComposingText(spannable_string_t*, int32_t relativeCursorPosition); + int32_t commitText(spannable_string_t*, int32_t relativeCursorPosition); + + void spellCheckingEnabled(bool); + + void setSelection(const Platform::IntPoint& startPoint, const Platform::IntPoint& endPoint); + void setCaretPosition(const Platform::IntPoint&); + void selectAtPoint(const Platform::IntPoint&); + void selectionCancelled(); + bool selectionContains(const Platform::IntPoint&); + + void popupListClosed(int size, bool* selecteds); + void popupListClosed(int index); + void setDateTimeInput(const WebString& value); + void setColorInput(const WebString& value); + + void onInputLocaleChanged(bool isRTL); + static void onNetworkAvailabilityChanged(bool available); + static void onCertificateStoreLocationSet(const WebString& caPath); + + WebString textHasAttribute(const WebString& query) const; + + ActiveNodeContext activeNodeContext(TargetDetectionStrategy) const; + + typedef intptr_t BackForwardId; + struct BackForwardEntry { + WebString url; + WebString originalUrl; + WebString title; + WebString networkToken; + BackForwardId id; + bool lastVisitWasHTTPNonGet; + }; + + bool canGoBackOrForward(int delta) const; + // Returns false if there is no page for the given delta (eg. + // attempt to go back with -1 when on the first page). + bool goBackOrForward(int delta); + void goToBackForwardEntry(BackForwardId); + + int backForwardListLength() const; + void getBackForwardList(SharedArray<BackForwardEntry>& result, unsigned& resultLength) const; + void releaseBackForwardEntry(BackForwardId) const; + void clearBackForwardList(bool keepCurrentPage) const; + + void addVisitedLink(const unsigned short* url, unsigned length); + +#if defined(ENABLE_WEBDOM) && ENABLE_WEBDOM + WebDOMDocument document() const; + WebDOMNode nodeAtPoint(int x, int y); + bool getNodeRect(const WebDOMNode&, Platform::IntRect& result); + bool setNodeFocus(const WebDOMNode&, bool on); + bool setNodeHovered(const WebDOMNode&, bool on); + bool nodeHasHover(const WebDOMNode&); +#endif + + bool defersLoading() const; + + bool willFireTimer(); + + bool isEnableLocalAccessToAllCookies() const; + void setEnableLocalAccessToAllCookies(bool); + + void enableWebInspector(); + void disableWebInspector(); + void enablePasswordEcho(); + void disablePasswordEcho(); + void dispatchInspectorMessage(const char* message, int length); + WebCore::Frame* mainFrame() const; + + // FIXME: Needs API review on this header. See PR #120402. + void notifyPagePause(); + void notifyPageResume(); + void notifyPageBackground(); + void notifyPageForeground(); + void notifyPageFullScreenAllowed(); + void notifyPageFullScreenExit(); + void notifyDeviceIdleStateChange(bool enterIdle); + void notifyAppActivationStateChange(ActivationStateType); + void notifySwipeEvent(); + void notifyScreenPowerStateChanged(bool powered); + void notifyFullScreenVideoExited(bool done); + void clearPluginSiteData(); + void setJavaScriptCanAccessClipboard(bool); + bool isWebGLEnabled() const; + void setWebGLEnabled(bool); + + void destroyWebPageCompositor(); + +private: + ~WebPage(); + + friend class WebKit::BackingStore; + friend class WebKit::BackingStoreClient; + friend class WebKit::BackingStorePrivate; + friend class WebKit::RenderQueue; + friend class WebKit::WebPageGroupLoadDeferrer; + friend class WebCore::ChromeClientBlackBerry; + friend class WebCore::FrameLoaderClientBlackBerry; + WebPagePrivate* d; +}; +} +} + +#endif // WebPage_h diff --git a/Source/WebKit/blackberry/Api/WebPageClient.h b/Source/WebKit/blackberry/Api/WebPageClient.h new file mode 100644 index 000000000..74b735c77 --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebPageClient.h @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef WebPageClient_h +#define WebPageClient_h + +#include "BlackBerryGlobal.h" +#include "WebString.h" + +#include <BlackBerryPlatformCursor.h> +#include <BlackBerryPlatformInputEvents.h> +#include <BlackBerryPlatformNavigationType.h> +#include <BlackBerryPlatformPrimitives.h> +#include <interaction/ScrollViewBase.h> +#include <vector> + +template<typename T> class ScopeArray; +template<typename T> class SharedArray; + +typedef void* WebFrame; + +namespace BlackBerry { + +namespace Platform { +class FilterStream; +class GeoTrackerListener; +class IntRectRegion; +class NetworkRequest; +class NetworkStreamFactory; + +namespace Graphics { +class Window; +} +} + +namespace WebKit { +class WebPage; + +class BLACKBERRY_EXPORT WebPageClient { +public: + virtual ~WebPageClient() { } + enum WindowStyleFlag { + FlagWindowHasMenuBar = 0x00000001, + FlagWindowHasToolBar = 0x00000002, + FlagWindowHasLocationBar = 0x00000004, + FlagWindowHasStatusBar = 0x00000008, + FlagWindowHasScrollBar = 0x00000010, + FlagWindowIsResizable = 0x00000020, + FlagWindowIsFullScreen = 0x00000040, + FlagWindowIsDialog = 0x00000080, + FlagWindowDefault = 0xFFFFFFFF, + }; + + enum FocusType { + FocusUnknown = 0, + FocusNone, + FocusCanvas, + FocusImage, + FocusInputButton, + FocusInputCheckBox, + FocusInputColor, + FocusInputDate, + FocusInputDateTime, + FocusInputDateTimeLocal, + FocusInputEmail, + FocusInputFile, + FocusInputImage, + FocusInputMonth, + FocusInputNumber, + FocusInputPassword, + FocusInputRadio, + FocusInputRange, + FocusInputReset, + FocusInputSearch, + FocusInputSubmit, + FocusInputTelephone, + FocusInputText, + FocusInputTime, + FocusInputURL, + FocusInputWeek, + FocusInputUnknown, + FocusLink, + FocusObject, + FocusSelect, + FocusSVGElement, + FocusTextArea, + FocusVideo, + }; + + enum AlertType { + MediaOK = 0, + MediaDecodeError, + MediaMetaDataError, + MediaMetaDataTimeoutError, + MediaNoMetaDataError, + MediaVideoReceiveError, + MediaAudioReceiveError, + MediaInvalidError, + }; + + virtual int getInstanceId() const = 0; + + virtual void notifyLoadStarted() = 0; + virtual void notifyLoadCommitted(const unsigned short* originalUrl, unsigned int originalUrlLength, const unsigned short* finalUrl, unsigned int finalUrlLength, const unsigned short* networkToken, unsigned int networkTokenLength) = 0; + virtual void notifyLoadFailedBeforeCommit(const unsigned short* originalUrl, unsigned int originalUrlLength, const unsigned short* finalUrl, unsigned int finalUrlLength, const unsigned short* networkToken, unsigned int networkTokenLength) = 0; + virtual void notifyLoadToAnchor(const unsigned short* url, unsigned int urlLength, const unsigned short* networkToken, unsigned int networkTokenLength) = 0; + virtual void notifyLoadProgress(int percentage) = 0; + virtual void notifyLoadReadyToRender(bool pageIsVisuallyNonEmpty) = 0; + virtual void notifyFirstVisuallyNonEmptyLayout() = 0; + virtual void notifyLoadFinished(int status) = 0; + virtual void notifyClientRedirect(const unsigned short* originalUrl, unsigned int originalUrlLength, const unsigned short* finalUrl, unsigned int finalUrlLength) = 0; + + virtual void notifyFrameDetached(const WebFrame) = 0; + + virtual void notifyRunLayoutTestsFinished() = 0; + + virtual void notifyInRegionScrollingStartingPointChanged(std::vector<Platform::ScrollViewBase>) = 0; + + virtual void notifyDocumentOnLoad() = 0; + + virtual void notifyWindowObjectCleared() = 0; + virtual WebString invokeClientJavaScriptCallback(const char* const* args, unsigned numArgs) = 0; + + virtual void addMessageToConsole(const unsigned short* message, unsigned messageLength, const unsigned short* source, unsigned sourceLength, unsigned lineNumber) = 0; + virtual int showAlertDialog(AlertType) = 0; + + virtual void runJavaScriptAlert(const unsigned short* message, unsigned messageLength, const char* origin, unsigned originLength) = 0; + virtual bool runJavaScriptConfirm(const unsigned short* message, unsigned messageLength, const char* origin, unsigned originLength) = 0; + virtual bool runJavaScriptPrompt(const unsigned short* message, unsigned messageLength, const unsigned short* defaultValue, unsigned defaultValueLength, const char* origin, unsigned originLength, WebString& result) = 0; + + virtual bool shouldInterruptJavaScript() = 0; + + virtual void javascriptSourceParsed(const unsigned short* url, unsigned urlLength, const unsigned short* script, unsigned scriptLength) = 0; + virtual void javascriptParsingFailed(const unsigned short* url, unsigned urlLength, const unsigned short* error, unsigned errorLength, int lineNumber) = 0; + virtual void javascriptPaused(const unsigned short* stack, unsigned stackLength) = 0; + virtual void javascriptContinued() = 0; + + // All of these methods use transformed coordinates. + virtual void contentsSizeChanged(const Platform::IntSize&) const = 0; + virtual void scrollChanged(const Platform::IntPoint&) const = 0; + virtual void zoomChanged(bool isMinZoomed, bool isMaxZoomed, bool isAtInitialZoom, double newZoom) const = 0; + + virtual void setPageTitle(const unsigned short* title, unsigned titleLength) = 0; + + virtual Platform::Graphics::Window* window() const = 0; + + virtual void notifyContentRendered(const Platform::IntRect&) = 0; + virtual void notifyScreenRotated() = 0; + + virtual void drawTapHighlight(const Platform::IntRectRegion&, int red, int green, int blue, int alpha, bool hideAfterScroll) = 0; + virtual void hideTapHighlight() = 0; + + virtual void focusChanged(FocusType, int elementId) = 0; + virtual void inputFocusGained(Platform::BlackBerryInputType, int inputStyle, bool waitForExplicitKeyboardShowCall) = 0; + virtual void inputFocusLost() = 0; + virtual void inputTextChanged() = 0; + virtual void inputSelectionChanged(unsigned selectionStart, unsigned selectionEnd) = 0; + virtual void inputLearnText(wchar_t* text, int length) = 0; + + virtual void showVirtualKeyboard(bool) = 0; + + virtual void checkSpellingOfString(const unsigned short* text, int length, int& misspellingLocation, int& misspellingLength) = 0; + virtual void requestSpellingSuggestionsForString(unsigned start, unsigned end) = 0; + + virtual void notifySelectionDetailsChanged(const Platform::IntRect& start, const Platform::IntRect& end, const Platform::IntRectRegion&) = 0; + virtual void cancelSelectionVisuals() = 0; + virtual void notifySelectionHandlesReversed() = 0; + virtual void notifyCaretChanged(const Platform::IntRect& caret, bool userTouchTriggered) = 0; + + virtual void cursorChanged(Platform::CursorType, const char* url, int x, int y) = 0; + + virtual void requestGeolocationPermission(Platform::GeoTrackerListener*, void* context, const char* origin, unsigned originLength) = 0; + virtual void cancelGeolocationPermission(Platform::GeoTrackerListener*, void* context) = 0; + virtual Platform::NetworkStreamFactory* networkStreamFactory() = 0; + + virtual void handleStringPattern(const unsigned short* pattern, unsigned length) = 0; + virtual void handleExternalLink(const Platform::NetworkRequest&, const unsigned short* context, unsigned contextLength, bool isClientRedirect) = 0; + + virtual void resetBackForwardList(unsigned listSize, unsigned currentIndex) = 0; + + virtual void openPopupList(bool multiple, int size, const ScopeArray<WebString>& labels, bool* enableds, const int* itemType, bool* selecteds) = 0; + virtual void openDateTimePopup(int type, const WebString& value, const WebString& min, const WebString& max, double step) = 0; + virtual void openColorPopup(const WebString& value) = 0; + + virtual bool chooseFilenames(bool allowMultiple, const WebString& acceptTypes, const SharedArray<WebString>& initialFiles, unsigned initialFileSize, SharedArray<WebString>& chosenFiles, unsigned& chosenFileSize) = 0; + + virtual void loadPluginForMimetype(int, int width, int height, const SharedArray<WebString>& paramNames, const SharedArray<WebString>& paramValues, int size, const char* url) = 0; + virtual void notifyPluginRectChanged(int, Platform::IntRect rectChanged) = 0; + virtual void destroyPlugin(int) = 0; + virtual void playMedia(int) = 0; + virtual void pauseMedia(int) = 0; + virtual float getTime(int) = 0; + virtual void setTime(int, float) = 0; + virtual void setVolume(int, float) = 0; + virtual void setMuted(int, bool) = 0; + + virtual WebPage* createWindow(int x, int y, int width, int height, unsigned flags, const WebString& url, const WebString& windowName) = 0; + + virtual void scheduleCloseWindow() = 0; + + // Database interface. + virtual unsigned long long databaseQuota(const unsigned short* origin, unsigned originLength, const unsigned short* databaseName, unsigned databaseNameLength, unsigned long long totalUsage, unsigned long long originUsage, unsigned long long estimatedSize) = 0; + + virtual void setIconForUrl(const char* originalPageUrl, const char* finalPageUrl, const char* iconUrl) = 0; + virtual void setFavicon(int width, int height, unsigned char* iconData, const char* url) = 0; + virtual void setLargeIcon(const char* iconUrl) = 0; + virtual void setWebAppCapable() = 0; + virtual void setSearchProviderDetails(const char* title, const char* documentUrl) = 0; + virtual void setAlternateFeedDetails(const char* title, const char* feedUrl) = 0; + + virtual WebString getErrorPage(int errorCode, const char* errorMessage, const char* url) = 0; + + virtual void willDeferLoading() = 0; + virtual void didResumeLoading() = 0; + + // Headers is a list of alternating key and value. + virtual void setMetaHeaders(const ScopeArray<WebString>& headers, unsigned int headersSize) = 0; + + virtual void needMoreData() = 0; + virtual void handleWebInspectorMessageToFrontend(int id, const char* message, int length) = 0; + + virtual bool hasPendingScrollOrZoomEvent() const = 0; + virtual Platform::IntRect userInterfaceBlittedDestinationRect() const = 0; + virtual Platform::IntRect userInterfaceBlittedVisibleContentsRect() const = 0; + + virtual void resetBitmapZoomScale(double scale) = 0; + virtual void animateBlockZoom(const Platform::FloatPoint& finalPoint, double finalScale) = 0; + + virtual void setPreventsScreenIdleDimming(bool noDimming) = 0; + virtual void authenticationChallenge(const unsigned short* realm, unsigned int realmLength, WebString& username, WebString& password) = 0; + + virtual bool shouldPluginEnterFullScreen() = 0; + virtual void didPluginEnterFullScreen() = 0; + virtual void didPluginExitFullScreen() = 0; + virtual void onPluginStartBackgroundPlay() = 0; + virtual void onPluginStopBackgroundPlay() = 0; + virtual bool lockOrientation(bool landscape) = 0; + virtual void unlockOrientation() = 0; + virtual bool isActive() const = 0; + virtual void requestWebGLPermission(const WebString&) = 0; + + virtual void setToolTip(WebString) = 0; + virtual void setStatus(WebString) = 0; + virtual bool acceptNavigationRequest(const Platform::NetworkRequest&, Platform::NavigationType) = 0; + virtual void cursorEventModeChanged(Platform::CursorEventMode) = 0; + virtual void touchEventModeChanged(Platform::TouchEventMode) = 0; + + virtual bool downloadAllowed(const char* url) = 0; + virtual void downloadRequested(const Platform::NetworkRequest&) = 0; + virtual void downloadRequested(Platform::FilterStream*, const WebString& suggestedFilename) = 0; + + virtual int fullscreenStart(const char* contextName, Platform::Graphics::Window*, unsigned x, unsigned y, unsigned width, unsigned height) = 0; + + virtual int fullscreenStop() = 0; + + virtual int fullscreenWindowSet(unsigned x, unsigned y, unsigned width, unsigned height) = 0; + + virtual void drawVerticalScrollbar() = 0; + virtual void drawHorizontalScrollbar() = 0; + virtual void populateCustomHeaders(Platform::NetworkRequest&) = 0; + + virtual void notifyWillUpdateApplicationCache() = 0; + virtual void notifyDidLoadFromApplicationCache() = 0; + + virtual void clearCookies() = 0; + virtual void clearCache() = 0; + + virtual bool hasKeyboardFocus() = 0; +}; +} // namespace WebKit +} // namespace BlackBerry + +#endif // WebPageClient_h diff --git a/Source/WebKit/blackberry/Api/WebPageGroupLoadDeferrer.cpp b/Source/WebKit/blackberry/Api/WebPageGroupLoadDeferrer.cpp new file mode 100644 index 000000000..084f2f42a --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebPageGroupLoadDeferrer.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "WebPageGroupLoadDeferrer.h" + +#include "PageGroupLoadDeferrer.h" +#include "WebPage.h" +#include "WebPage_p.h" + +namespace BlackBerry { +namespace WebKit { + +WebPageGroupLoadDeferrer::WebPageGroupLoadDeferrer(WebPage* webPage) +{ + WebCore::TimerBase::fireTimersInNestedEventLoop(); + m_pageGroupLoadDeferrer = new WebCore::PageGroupLoadDeferrer(webPage->d->m_page, true /* defer the page itself */); +} + +WebPageGroupLoadDeferrer::~WebPageGroupLoadDeferrer() +{ + delete m_pageGroupLoadDeferrer; +} + +} // namespace WebKit +} // namespace BlackBerry diff --git a/Source/WebKit/blackberry/Api/WebPageGroupLoadDeferrer.h b/Source/WebKit/blackberry/Api/WebPageGroupLoadDeferrer.h new file mode 100644 index 000000000..cb651ed9d --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebPageGroupLoadDeferrer.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef WebPageGroupLoadDeferrer_h +#define WebPageGroupLoadDeferrer_h + +#include "BlackBerryGlobal.h" + +namespace WebCore { +class PageGroupLoadDeferrer; +} + +namespace BlackBerry { +namespace WebKit { + +class WebPage; + +// WebPageGroupLoadDeferrer is supposed to be used in the same way as WebCore::PageGroupLoadDeferrer. +// Declare a WebPageGroupLoadDeferrer object in the scope where the page group should defer loading and DOM timers. +class BLACKBERRY_EXPORT WebPageGroupLoadDeferrer { +public: + explicit WebPageGroupLoadDeferrer(WebPage*); + ~WebPageGroupLoadDeferrer(); +private: + WebCore::PageGroupLoadDeferrer* m_pageGroupLoadDeferrer; +}; + +} // namespace WebKit +} // namespace BlackBerry + +#endif // WebPageGroupLoadDeferrer_h diff --git a/Source/WebKit/blackberry/Api/WebPage_p.h b/Source/WebKit/blackberry/Api/WebPage_p.h new file mode 100644 index 000000000..e0238b6d6 --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebPage_p.h @@ -0,0 +1,517 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef WebPage_p_h +#define WebPage_p_h + +#include "ChromeClient.h" +#if USE(ACCELERATED_COMPOSITING) +#include "LayerRenderer.h" +#endif +#include "PageClientBlackBerry.h" +#include "PlatformMouseEvent.h" +#include "ScriptSourceCode.h" +#include "Timer.h" +#include "ViewportArguments.h" +#include "WebPage.h" +#include "WebSettings.h" + +#include <BlackBerryPlatformMessage.h> + +namespace WebCore { +class DOMWrapperWorld; +class Document; +class Frame; +class FrameView; +class GeolocationControllerClientBlackBerry; +class JavaScriptDebuggerBlackBerry; +class KURL; +class Node; +class Page; +class PluginView; +class RenderLayer; +class RenderObject; +class ScrollView; +class TransformationMatrix; +template<typename T> class Timer; +} + +namespace BlackBerry { +namespace WebKit { + +class BackingStore; +class BackingStoreClient; +class BackingStoreTile; +class DumpRenderTreeClient; +class InPageSearchManager; +class InputHandler; +class InRegionScrollableArea; +class SelectionHandler; +class TouchEventHandler; +class WebPageClient; + +#if USE(ACCELERATED_COMPOSITING) +class FrameLayers; +class WebPageCompositor; +#endif + +// In the client code, there is screen size and viewport. +// In WebPagePrivate, the screen size is called the transformedViewportSize, +// the viewport position is called the transformedScrollPosition, +// and the viewport size is called the transformedActualVisibleSize. +class WebPagePrivate : public PageClientBlackBerry, public WebSettingsDelegate, public Platform::GuardedPointerBase { +public: + enum ViewMode { Mobile, Desktop, FixedDesktop }; + enum LoadState { None /* on instantiation of page */, Provisional, Committed, Finished, Failed }; + + WebPagePrivate(WebPage*, WebPageClient*, const WebCore::IntRect&); + virtual ~WebPagePrivate(); + + void init(const WebString& pageGroupName); + bool handleMouseEvent(WebCore::PlatformMouseEvent&); + bool handleWheelEvent(WebCore::PlatformWheelEvent&); + + void load(const char* url, const char* networkToken, const char* method, Platform::NetworkRequest::CachePolicy, const char* data, size_t dataLength, const char* const* headers, size_t headersLength, bool isInitial, bool mustHandleInternally = false, bool forceDownload = false, const char* overrideContentType = ""); + void loadString(const char* string, const char* baseURL, const char* mimeType, const char* failingURL = 0); + bool executeJavaScript(const char* script, JavaScriptDataType& returnType, WebString& returnValue); + bool executeJavaScriptInIsolatedWorld(const WebCore::ScriptSourceCode&, JavaScriptDataType& returnType, WebString& returnValue); + + void stopCurrentLoad(); + void prepareToDestroy(); + + LoadState loadState() const { return m_loadState; } + bool isLoading() const { return m_loadState == WebPagePrivate::Provisional || m_loadState == WebPagePrivate::Committed; } + + // Called from within WebKit via FrameLoaderClientBlackBerry. + void setLoadState(LoadState); + + // Clamp the scale. + double clampedScale(double scale) const; + + // Determine if we should zoom, clamping the scale parameter if required. + bool shouldZoomAboutPoint(double scale, const WebCore::FloatPoint& anchor, bool enforeScaleClamping, double* clampedScale); + + // Scale the page to the given scale and anchor about the point which is specified in untransformed content coordinates. + bool zoomAboutPoint(double scale, const WebCore::FloatPoint& anchor, bool enforceScaleClamping = true, bool forceRendering = false, bool isRestoringZoomLevel = false); + bool scheduleZoomAboutPoint(double scale, const WebCore::FloatPoint& anchor, bool enforceScaleClamping = true, bool forceRendering = false); + void unscheduleZoomAboutPoint(); + WebCore::IntPoint calculateReflowedScrollPosition(const WebCore::FloatPoint& anchorOffset, double inverseScale); + void setTextReflowAnchorPoint(const Platform::IntPoint& focalPoint); + + void schedulePinchZoomAboutPoint(double scale, const WebCore::IntPoint& anchor); + + // Perform actual zoom for block zoom. + void zoomBlock(); + + // Called by the backing store as well as the method below. + void requestLayoutIfNeeded() const; + void setNeedsLayout(); + + WebCore::IntPoint scrollPosition() const; + WebCore::IntPoint maximumScrollPosition() const; + void setScrollPosition(const WebCore::IntPoint&); + bool scrollBy(int deltaX, int deltaY, bool scrollMainFrame = true); + + void enqueueRenderingOfClippedContentOfScrollableNodeAfterInRegionScrolling(WebCore::Node*); + std::vector<Platform::ScrollViewBase> inRegionScrollableAreasForPoint(const Platform::IntPoint&); + void notifyInRegionScrollStatusChanged(bool status); + void setScrollOriginPoint(const Platform::IntPoint&); + void setHasInRegionScrollableAreas(bool); + + // The actual visible size as reported by the client, but in WebKit coordinates. + WebCore::IntSize actualVisibleSize() const; + + // The viewport size is the same as the client's window size, but in webkit coordinates. + WebCore::IntSize viewportSize() const; + + // Modifies the zoomToFit algorithm logic to construct a scale such that the viewportSize above is equal to this size. + bool hasVirtualViewport() const; + bool isUserScalable() const { return m_userScalable; } + void setUserScalable(bool userScalable) { m_userScalable = userScalable; } + + // Sets default layout size without doing layout or marking as needing layout. + void setDefaultLayoutSize(const WebCore::IntSize&); + + // Updates WebCore when the viewportSize() or actualVisibleSize() change. + void updateViewportSize(bool setFixedReportedSize = true, bool sendResizeEvent = true); + + WebCore::FloatPoint centerOfVisibleContentsRect() const; + WebCore::IntRect visibleContentsRect() const; + WebCore::IntSize contentsSize() const; + WebCore::IntSize absoluteVisibleOverflowSize() const; + + // Virtual functions inherited from PageClientBlackBerry. + virtual void setCursor(WebCore::PlatformCursorHandle); + virtual Platform::NetworkStreamFactory* networkStreamFactory(); + virtual Platform::Graphics::Window* platformWindow() const; + virtual void setPreventsScreenDimming(bool preventDimming); + virtual void showVirtualKeyboard(bool showKeyboard); + virtual void ensureContentVisible(bool centerInView = true); + virtual void zoomToContentRect(const WebCore::IntRect&); + virtual void registerPlugin(WebCore::PluginView*, bool); + virtual void notifyPageOnLoad(); + virtual bool shouldPluginEnterFullScreen(WebCore::PluginView*, const char*); + virtual void didPluginEnterFullScreen(WebCore::PluginView*, const char*); + virtual void didPluginExitFullScreen(WebCore::PluginView*, const char*); + virtual void onPluginStartBackgroundPlay(WebCore::PluginView*, const char*); + virtual void onPluginStopBackgroundPlay(WebCore::PluginView*, const char*); + virtual bool lockOrientation(bool landscape); + virtual void unlockOrientation(); + virtual int orientation() const; + virtual double currentZoomFactor() const; + virtual int showAlertDialog(WebPageClient::AlertType atype); + virtual bool isActive() const; + + // Called from within WebKit via ChromeClientBlackBerry. + void enterFullscreenForNode(WebCore::Node*); + void exitFullscreenForNode(WebCore::Node*); + void contentsSizeChanged(const WebCore::IntSize&); + void overflowExceedsContentsSize() { m_overflowExceedsContentsSize = true; } + void layoutFinished(); + void setNeedTouchEvents(bool); + + // Called according to our heuristic or from setLoadState depending on whether we have a virtual viewport. + void zoomToInitialScaleOnLoad(); + + // Various scale factors. + double currentScale() const { return m_transformationMatrix->m11(); } + double zoomToFitScale() const; + double initialScale() const; + void setInitialScale(double scale) { m_initialScale = scale; } + double minimumScale() const + { + return (m_minimumScale > zoomToFitScale() && m_minimumScale <= maximumScale()) ? m_minimumScale : zoomToFitScale(); + } + + void setMinimumScale(double scale) { m_minimumScale = scale; } + double maximumScale() const; + void setMaximumScale(double scale) { m_maximumScale = scale; } + void resetScales(); + + // Note: to make this reflow width transform invariant just use + // transformedActualVisibleSize() here instead! + int reflowWidth() const { return actualVisibleSize().width(); } + + // These methods give the real geometry of the device given the currently set transform. + WebCore::IntPoint transformedScrollPosition() const; + WebCore::IntPoint transformedMaximumScrollPosition() const; + WebCore::IntSize transformedActualVisibleSize() const; + WebCore::IntSize transformedViewportSize() const; + WebCore::IntRect transformedVisibleContentsRect() const; + WebCore::IntSize transformedContentsSize() const; + + // Generic conversions of points, rects, relative to and from contents and viewport. + WebCore::IntPoint mapFromContentsToViewport(const WebCore::IntPoint&) const; + WebCore::IntPoint mapFromViewportToContents(const WebCore::IntPoint&) const; + WebCore::IntRect mapFromContentsToViewport(const WebCore::IntRect&) const; + WebCore::IntRect mapFromViewportToContents(const WebCore::IntRect&) const; + + // Generic conversions of points, rects, relative to and from transformed contents and transformed viewport. + WebCore::IntPoint mapFromTransformedContentsToTransformedViewport(const WebCore::IntPoint&) const; + WebCore::IntPoint mapFromTransformedViewportToTransformedContents(const WebCore::IntPoint&) const; + WebCore::IntRect mapFromTransformedContentsToTransformedViewport(const WebCore::IntRect&) const; + WebCore::IntRect mapFromTransformedViewportToTransformedContents(const WebCore::IntRect&) const; + + // Generic conversions of points, rects, and sizes to and from transformed coordinates. + WebCore::IntPoint mapToTransformed(const WebCore::IntPoint&) const; + WebCore::FloatPoint mapToTransformedFloatPoint(const WebCore::FloatPoint&) const; + WebCore::IntPoint mapFromTransformed(const WebCore::IntPoint&) const; + WebCore::FloatPoint mapFromTransformedFloatPoint(const WebCore::FloatPoint&) const; + WebCore::FloatRect mapFromTransformedFloatRect(const WebCore::FloatRect&) const; + WebCore::IntSize mapToTransformed(const WebCore::IntSize&) const; + WebCore::IntSize mapFromTransformed(const WebCore::IntSize&) const; + WebCore::IntRect mapToTransformed(const WebCore::IntRect&) const; + void clipToTransformedContentsRect(WebCore::IntRect&) const; + WebCore::IntRect mapFromTransformed(const WebCore::IntRect&) const; + bool transformedPointEqualsUntransformedPoint(const WebCore::IntPoint& transformedPoint, const WebCore::IntPoint& untransformedPoint); + + // Notification methods that deliver changes to the real geometry of the device as specified above. + void notifyTransformChanged(); + void notifyTransformedContentsSizeChanged(); + void notifyTransformedScrollChanged(); + + void assignFocus(Platform::FocusDirection); + Platform::IntRect focusNodeRect(); + WebCore::IntRect getRecursiveVisibleWindowRect(WebCore::ScrollView*, bool noClipOfMainFrame = false); + + WebCore::IntPoint frameOffset(const WebCore::Frame*) const; + + WebCore::Node* bestNodeForZoomUnderPoint(const WebCore::IntPoint&); + WebCore::Node* bestChildNodeForClickRect(WebCore::Node* parentNode, const WebCore::IntRect& clickRect); + WebCore::Node* nodeForZoomUnderPoint(const WebCore::IntPoint&); + WebCore::Node* adjustedBlockZoomNodeForZoomLimits(WebCore::Node*); + WebCore::IntRect rectForNode(WebCore::Node*); + WebCore::IntRect blockZoomRectForNode(WebCore::Node*); + WebCore::IntRect adjustRectOffsetForFrameOffset(const WebCore::IntRect&, const WebCore::Node*); + bool compareNodesForBlockZoom(WebCore::Node* n1, WebCore::Node* n2); + double newScaleForBlockZoomRect(const WebCore::IntRect&, double oldScale, double margin); + double maxBlockZoomScale() const; + + // Plugin Methods. + void notifyPluginRectChanged(int id, const WebCore::IntRect& rectChanged); + + // Context Methods. + ActiveNodeContext activeNodeContext(TargetDetectionStrategy); + PassRefPtr<WebCore::Node> contextNode(TargetDetectionStrategy); + +#if ENABLE(VIEWPORT_REFLOW) + void toggleTextReflowIfEnabledForBlockZoomOnly(bool shouldEnableTextReflow = false); +#endif + + void selectionChanged(WebCore::Frame*); + + void updateDelegatedOverlays(bool dispatched = false); + + void updateCursor(); + + void onInputLocaleChanged(bool isRTL); + + ViewMode viewMode() const { return m_viewMode; } + bool setViewMode(ViewMode); // Returns true if the change requires re-layout. + + void setShouldUseFixedDesktopMode(bool b) { m_shouldUseFixedDesktopMode = b; } + + bool useFixedLayout() const; + WebCore::IntSize fixedLayoutSize(bool snapToIncrement = false) const; + + // ZoomToFitOnLoad can lead to a large recursion depth in FrameView::layout() as we attempt + // to determine the zoom scale factor so as to have the content of the page fit within the + // area of the frame. From observation, we can bail out after a recursion depth of 10 and + // still have reasonable results. + bool didLayoutExceedMaximumIterations() const { return m_nestedLayoutFinishedCount > 10; } + + void clearFocusNode(); + WebCore::Frame* focusedOrMainFrame() const; + WebCore::Frame* mainFrame() const { return m_mainFrame; } + + bool scrollNodeRecursively(WebCore::Node* originalNode, const WebCore::IntSize& delta); + bool scrollRenderer(WebCore::RenderObject* renderer, const WebCore::IntSize& delta); + void adjustScrollDelta(const WebCore::IntPoint& maxOffset, const WebCore::IntPoint& currentOffset, WebCore::IntSize& delta) const; + + bool canScrollRenderBox(WebCore::RenderBox*); + bool canScrollInnerFrame(WebCore::Frame*) const; + +#if ENABLE(EVENT_MODE_METATAGS) + void didReceiveCursorEventMode(WebCore::CursorEventMode); + void didReceiveTouchEventMode(WebCore::TouchEventMode); +#endif + + void dispatchViewportPropertiesDidChange(const WebCore::ViewportArguments&); + WebCore::IntSize recomputeVirtualViewportFromViewportArguments(); + + void resetBlockZoom(); + + void zoomAboutPointTimerFired(WebCore::Timer<WebPagePrivate>*); + bool shouldSendResizeEvent(); + void scrollEventTimerFired(WebCore::Timer<WebPagePrivate>*); + void resizeEventTimerFired(WebCore::Timer<WebPagePrivate>*); + + // If this url should be handled as a pattern, returns the pattern + // otherwise, returns an empty string. + String findPatternStringForUrl(const WebCore::KURL&) const; + + void suspendBackingStore(); + void resumeBackingStore(); + + void setShouldResetTilesWhenShown(bool flag) { m_shouldResetTilesWhenShown = flag; } + bool shouldResetTilesWhenShown() const { return m_shouldResetTilesWhenShown; } + + void setScreenOrientation(int); + + // Scroll and/or zoom so that the WebPage fits the new actual + // visible size. + void setViewportSize(const WebCore::IntSize& transformedActualVisibleSize, bool ensureFocusElementVisible); + void screenRotated(); // Helper method for setViewportSize(). + + void scheduleDeferrableTimer(WebCore::Timer<WebPagePrivate>*, double timeOut); + void unscheduleAllDeferrableTimers(); + void willDeferLoading(); + void didResumeLoading(); + + // Returns true if the escape key handler should zoom. + bool shouldZoomOnEscape() const; + + WebCore::TransformationMatrix* transformationMatrix() const + { + return m_transformationMatrix; + } + +#if USE(ACCELERATED_COMPOSITING) + // WebKit thread. + bool needsOneShotDrawingSynchronization(); + void rootLayerCommitTimerFired(WebCore::Timer<WebPagePrivate>*); + bool commitRootLayerIfNeeded(); + WebCore::LayerRenderingResults lastCompositingResults() const; + + // WebKit thread, plumbed through from ChromeClientBlackBerry. + void setRootLayerWebKitThread(WebCore::Frame*, WebCore::LayerWebKitThread*); + void setNeedsOneShotDrawingSynchronization(); + void scheduleRootLayerCommit(); + + // Thread safe. + void resetCompositingSurface(); + void drawLayersOnCommit(); // Including backing store blit. + bool drawSubLayers(const WebCore::IntRect& dstRect, const WebCore::FloatRect& contents); + bool drawSubLayers(); // Draw them at last known position. + + // Compositing thread. + void setRootLayerCompositingThread(WebCore::LayerCompositingThread*); + void commitRootLayer(const WebCore::IntRect&, const WebCore::IntSize&); + void setIsAcceleratedCompositingActive(bool); + void destroyCompositor(); + void syncDestroyCompositorOnCompositingThread(); + void destroyLayerResources(); + void suspendRootLayerCommit(); + void resumeRootLayerCommit(); + void blitVisibleContents(); +#endif + + bool dispatchTouchEventToFullScreenPlugin(WebCore::PluginView*, const Platform::TouchEvent&); + bool dispatchTouchPointAsMouseEventToFullScreenPlugin(WebCore::PluginView*, const Platform::TouchPoint&); + bool dispatchMouseEventToFullScreenPlugin(WebCore::PluginView*, const Platform::MouseEvent&); + + BackingStoreClient* backingStoreClientForFrame(const WebCore::Frame*) const; + void addBackingStoreClientForFrame(const WebCore::Frame*, BackingStoreClient*); + void removeBackingStoreClientForFrame(const WebCore::Frame*); + + // Clean up any document related data we might be holding. + void clearDocumentData(const WebCore::Document*); + + static WebCore::RenderLayer* enclosingPositionedAncestorOrSelfIfPositioned(WebCore::RenderLayer*); + static WebCore::RenderLayer* enclosingFixedPositionedAncestorOrSelfIfFixedPositioned(WebCore::RenderLayer*); + + static WebCore::IntSize defaultMaxLayoutSize(); + + WebPage* m_webPage; + WebPageClient* m_client; + WebCore::Page* m_page; + WebCore::Frame* m_mainFrame; + RefPtr<WebCore::Node> m_currentContextNode; + WebSettings* m_webSettings; + +#if ENABLE(JAVASCRIPT_DEBUGGER) + OwnPtr<WebCore::JavaScriptDebuggerBlackBerry> m_scriptDebugger; +#endif + + bool m_visible; + bool m_shouldResetTilesWhenShown; + bool m_userScalable; + bool m_userPerformedManualZoom; + bool m_userPerformedManualScroll; + bool m_contentsSizeChanged; + bool m_overflowExceedsContentsSize; + bool m_resetVirtualViewportOnCommitted; + bool m_shouldUseFixedDesktopMode; + bool m_needTouchEvents; + int m_preventIdleDimmingCount; + +#if ENABLE(TOUCH_EVENTS) + bool m_preventDefaultOnTouchStart; +#endif + unsigned m_nestedLayoutFinishedCount; + WebCore::IntSize m_previousContentsSize; + int m_actualVisibleWidth; + int m_actualVisibleHeight; + int m_virtualViewportWidth; + int m_virtualViewportHeight; + WebCore::IntSize m_defaultLayoutSize; + WebCore::ViewportArguments m_viewportArguments; // We keep this around since we may need to re-evaluate the arguments on rotation. + bool m_didRestoreFromPageCache; + ViewMode m_viewMode; + LoadState m_loadState; + WebCore::TransformationMatrix* m_transformationMatrix; + BackingStore* m_backingStore; + BackingStoreClient* m_backingStoreClient; + InPageSearchManager* m_inPageSearchManager; + InputHandler* m_inputHandler; + SelectionHandler* m_selectionHandler; + TouchEventHandler* m_touchEventHandler; + +#if ENABLE(EVENT_MODE_METATAGS) + WebCore::CursorEventMode m_cursorEventMode; + WebCore::TouchEventMode m_touchEventMode; +#endif + + Platform::BlackBerryCursor m_currentCursor; + + DumpRenderTreeClient* m_dumpRenderTree; + + double m_initialScale; + double m_minimumScale; + double m_maximumScale; + + // Block zoom animation data. + WebCore::FloatPoint m_finalBlockPoint; + WebCore::FloatPoint m_finalBlockPointReflowOffset; + double m_blockZoomFinalScale; + RefPtr<WebCore::Node> m_currentPinchZoomNode; + WebCore::FloatPoint m_anchorInNodeRectRatio; + RefPtr<WebCore::Node> m_currentBlockZoomNode; + RefPtr<WebCore::Node> m_currentBlockZoomAdjustedNode; + bool m_shouldReflowBlock; + + // Delayed zoomAboutPoint. + OwnPtr<WebCore::Timer<WebPagePrivate> > m_delayedZoomTimer; + struct { + double scale; + WebCore::FloatPoint anchor; + bool enforceScaleClamping; + bool forceRendering; + } m_delayedZoomArguments; + + double m_lastUserEventTimestamp; // Used to detect user scrolling. + + WebCore::PlatformMouseEvent m_lastMouseEvent; + bool m_pluginMouseButtonPressed; // Used to track mouse button for full screen plugins. + bool m_pluginMayOpenNewTab; + + WebCore::GeolocationControllerClientBlackBerry* m_geolocationClient; + + HashSet<WebCore::PluginView*> m_pluginViews; + + RefPtr<WebCore::Node> m_inRegionScrollStartingNode; + +#if USE(ACCELERATED_COMPOSITING) + bool m_isAcceleratedCompositingActive; + OwnPtr<FrameLayers> m_frameLayers; // WebKit thread only. + OwnPtr<WebPageCompositor> m_compositor; // Compositing thread only. + OwnPtr<WebCore::Timer<WebPagePrivate> > m_rootLayerCommitTimer; + bool m_needsOneShotDrawingSynchronization; + bool m_needsCommit; + bool m_suspendRootLayerCommit; +#endif + + int m_pendingOrientation; + + RefPtr<WebCore::Node> m_fullscreenVideoNode; + RefPtr<WebCore::PluginView> m_fullScreenPluginView; + + typedef HashMap<const WebCore::Frame*, BackingStoreClient*> BackingStoreClientForFrameMap; + BackingStoreClientForFrameMap m_backingStoreClientForFrameMap; + + // WebSettingsDelegate methods. + virtual void didChangeSettings(WebSettings*); + + RefPtr<WebCore::DOMWrapperWorld> m_isolatedWorld; + bool m_hasInRegionScrollableAreas; + bool m_updateDelegatedOverlaysDispatched; +}; +} +} + +#endif // WebPage_p_h diff --git a/Source/WebKit/blackberry/Api/WebSettings.cpp b/Source/WebKit/blackberry/Api/WebSettings.cpp new file mode 100644 index 000000000..960964cd8 --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebSettings.cpp @@ -0,0 +1,816 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "WebSettings.h" + +#include "WebSettings_p.h" + +#include "WebString.h" +#include <Base64.h> +#include <Color.h> +#include <PageCache.h> +#include <wtf/HashSet.h> +#include <wtf/Vector.h> + +namespace BlackBerry { +namespace WebKit { + +DEFINE_STATIC_LOCAL(String, BlackBerryAllowCrossSiteRequests, ("BlackBerryAllowCrossSiteRequests")); +DEFINE_STATIC_LOCAL(String, BlackBerryBackgroundColor, ("BlackBerryBackgroundColor")); +DEFINE_STATIC_LOCAL(String, BlackBerryCookiesEnabled, ("BlackBerryCookiesEnabled")); +DEFINE_STATIC_LOCAL(String, BlackBerryDirectRenderingToWindowEnabled, ("BlackBerryDirectRenderingToWindowEnabled")); +DEFINE_STATIC_LOCAL(String, BlackBerryDrawBorderWhileLoadingImages, ("BlackBerryDrawBorderWhileLoadingImages")); +DEFINE_STATIC_LOCAL(String, BlackBerryEmailModeEnabled, ("BlackBerryEmailModeEnabled")); +DEFINE_STATIC_LOCAL(String, BlackBerryGetFocusNodeContextEnabled, ("BlackBerryGetFocusNodeContextEnabled")); +DEFINE_STATIC_LOCAL(String, BlackBerryHandlePatternURLs, ("BlackBerryHandlePatternURLs")); +DEFINE_STATIC_LOCAL(String, BlackBerryInitialScale, ("BlackBerryInitialScale")); +DEFINE_STATIC_LOCAL(String, BlackBerryLinksHandledExternallyEnabled, ("BlackBerryLinksHandledExternallyEnabled")); +DEFINE_STATIC_LOCAL(String, BlackBerryMaxPluginInstances, ("BlackBerryMaxPluginInstances")); +DEFINE_STATIC_LOCAL(String, BlackBerryOverZoomColor, ("BlackBerryOverZoomColor")); +DEFINE_STATIC_LOCAL(String, BlackBerryRenderAnimationsOnScrollOrZoomEnabled, ("BlackBerryRenderAnimationsOnScrollOrZoomEnabled")); +DEFINE_STATIC_LOCAL(String, BlackBerryScrollbarsEnabled, ("BlackBerryScrollbarsEnabled")); +DEFINE_STATIC_LOCAL(String, BlackBerryTextReflowMode, ("BlackBerryTextReflowMode")); +DEFINE_STATIC_LOCAL(String, BlackBerryUseRTLWritingDirection, ("BlackBerryUseRTLWritingDirection")); +DEFINE_STATIC_LOCAL(String, BlackBerryUseWebKitCache, ("BlackBerryUseWebKitCache")); +DEFINE_STATIC_LOCAL(String, BlackBerryUserAgentString, ("BlackBerryUserAgentString")); +DEFINE_STATIC_LOCAL(String, BlackBerryUserScalableEnabled, ("BlackBerryUserScalableEnabled")); +DEFINE_STATIC_LOCAL(String, BlackBerryViewportWidth, ("BlackBerryViewportWidth")); +DEFINE_STATIC_LOCAL(String, BlackBerryZoomToFitOnLoadEnabled, ("BlackBerryZoomToFitOnLoadEnabled")); +DEFINE_STATIC_LOCAL(String, WebKitDatabasePath, ("WebKitDatabasePath")); +DEFINE_STATIC_LOCAL(String, WebKitDatabasesEnabled, ("WebKitDatabasesEnabled")); +DEFINE_STATIC_LOCAL(String, WebKitDefaultFixedFontSize, ("WebKitDefaultFixedFontSize")); +DEFINE_STATIC_LOCAL(String, WebKitDefaultFontSize, ("WebKitDefaultFontSize")); +DEFINE_STATIC_LOCAL(String, WebKitDefaultTextEncodingName, ("WebKitDefaultTextEncodingName")); +DEFINE_STATIC_LOCAL(String, WebKitDownloadableBinaryFontsEnabled, ("WebKitDownloadableBinaryFontsEnabled")); +DEFINE_STATIC_LOCAL(String, WebKitFirstScheduledLayoutDelay, ("WebKitFirstScheduledLayoutDelay")); +DEFINE_STATIC_LOCAL(String, WebKitFixedFontFamily, ("WebKitFixedFontFamily")); +DEFINE_STATIC_LOCAL(String, WebKitFrameFlatteningEnabled, ("WebKitFrameFlatteningEnabled")); +DEFINE_STATIC_LOCAL(String, WebKitGeolocationEnabled, ("WebKitGeolocationEnabled")); +DEFINE_STATIC_LOCAL(String, WebKitJavaScriptCanOpenWindowsAutomaticallyEnabled, ("WebKitJavaScriptCanOpenWindowsAutomaticallyEnabled")); +DEFINE_STATIC_LOCAL(String, WebKitJavaScriptEnabled, ("WebKitJavaScriptEnabled")); +DEFINE_STATIC_LOCAL(String, WebKitLoadsImagesAutomatically, ("WebKitLoadsImagesAutomatically")); +DEFINE_STATIC_LOCAL(String, WebKitLocalStorageEnabled, ("WebKitLocalStorageEnabled")); +DEFINE_STATIC_LOCAL(String, WebKitLocalStoragePath, ("WebKitLocalStoragePath")); +DEFINE_STATIC_LOCAL(String, WebKitLocalStorageQuota, ("WebKitLocalStorageQuota")); +DEFINE_STATIC_LOCAL(String, WebKitMaximumPagesInCache, ("WebKitMaximumPagesInCache")); +DEFINE_STATIC_LOCAL(String, WebKitMinimumFontSize, ("WebKitMinimumFontSize")); +DEFINE_STATIC_LOCAL(String, WebKitOfflineWebApplicationCacheEnabled, ("WebKitOfflineWebApplicationCacheEnabled")); +DEFINE_STATIC_LOCAL(String, WebKitOfflineWebApplicationCachePath, ("WebKitOfflineWebApplicationCachePath")); +DEFINE_STATIC_LOCAL(String, WebKitPageGroupName, ("WebKitPageGroupName")); +DEFINE_STATIC_LOCAL(String, WebKitPluginsEnabled, ("WebKitPluginsEnabled")); +DEFINE_STATIC_LOCAL(String, WebKitPrivateBrowsingEnabled, ("WebKitPrivateBrowsingEnabled")); +DEFINE_STATIC_LOCAL(String, WebKitSansSeriffFontFamily, ("WebKitSansSeriffFontFamily")); +DEFINE_STATIC_LOCAL(String, WebKitSeriffFontFamily, ("WebKitSeriffFontFamily")); +DEFINE_STATIC_LOCAL(String, WebKitStandardFontFamily, ("WebKitStandardFontFamily")); +DEFINE_STATIC_LOCAL(String, WebKitUserStyleSheet, ("WebKitUserStyleSheet")); +DEFINE_STATIC_LOCAL(String, WebKitUserStyleSheetLocation, ("WebKitUserStyleSheetLocation")); +DEFINE_STATIC_LOCAL(String, WebKitWebSocketsEnabled, ("WebKitWebSocketsEnabled")); +DEFINE_STATIC_LOCAL(String, WebKitXSSAuditorEnabled, ("WebKitXSSAuditorEnabled")); +DEFINE_STATIC_LOCAL(String, SpatialNavigationEnabled, ("SpatialNavigationEnabled")); + +// FIXME: We should consider moving all the mime type code into its own object. + +typedef HashMap<String, WebString> MIMETypeAssociationMap; + +static const MIMETypeAssociationMap& mimeTypeAssociationMap() +{ + static MIMETypeAssociationMap* mimeTypeMap = 0; + if (mimeTypeMap) + return *mimeTypeMap; + + mimeTypeMap = new MIMETypeAssociationMap; + mimeTypeMap->add("image/x-ms-bmp", "image/bmp"); + mimeTypeMap->add("image/x-windows-bmp", "image/bmp"); + mimeTypeMap->add("image/x-bmp", "image/bmp"); + mimeTypeMap->add("image/x-bitmap", "image/bmp"); + mimeTypeMap->add("image/x-ms-bitmap", "image/bmp"); + mimeTypeMap->add("image/jpg", "image/jpeg"); + mimeTypeMap->add("image/pjpeg", "image/jpeg"); + mimeTypeMap->add("image/x-png", "image/png"); + mimeTypeMap->add("image/vnd.rim.png", "image/png"); + mimeTypeMap->add("image/ico", "image/vnd.microsoft.icon"); + mimeTypeMap->add("image/icon", "image/vnd.microsoft.icon"); + mimeTypeMap->add("text/ico", "image/vnd.microsoft.icon"); + mimeTypeMap->add("application/ico", "image/vnd.microsoft.icon"); + mimeTypeMap->add("image/x-icon", "image/vnd.microsoft.icon"); + mimeTypeMap->add("audio/vnd.qcelp", "audio/qcelp"); + mimeTypeMap->add("audio/qcp", "audio/qcelp"); + mimeTypeMap->add("audio/vnd.qcp", "audio/qcelp"); + mimeTypeMap->add("audio/wav", "audio/x-wav"); + mimeTypeMap->add("audio/mid", "audio/midi"); + mimeTypeMap->add("audio/sp-midi", "audio/midi"); + mimeTypeMap->add("audio/x-mid", "audio/midi"); + mimeTypeMap->add("audio/x-midi", "audio/midi"); + mimeTypeMap->add("audio/x-mpeg", "audio/mpeg"); + mimeTypeMap->add("audio/mp3", "audio/mpeg"); + mimeTypeMap->add("audio/x-mp3", "audio/mpeg"); + mimeTypeMap->add("audio/mpeg3", "audio/mpeg"); + mimeTypeMap->add("audio/x-mpeg3", "audio/mpeg"); + mimeTypeMap->add("audio/mpg3", "audio/mpeg"); + mimeTypeMap->add("audio/mpg", "audio/mpeg"); + mimeTypeMap->add("audio/x-mpg", "audio/mpeg"); + mimeTypeMap->add("audio/m4a", "audio/mp4"); + mimeTypeMap->add("audio/x-m4a", "audio/mp4"); + mimeTypeMap->add("audio/x-mp4", "audio/mp4"); + mimeTypeMap->add("audio/x-aac", "audio/aac"); + mimeTypeMap->add("audio/x-amr", "audio/amr"); + mimeTypeMap->add("audio/mpegurl", "audio/x-mpegurl"); + mimeTypeMap->add("video/3gp", "video/3gpp"); + mimeTypeMap->add("video/avi", "video/x-msvideo"); + mimeTypeMap->add("video/x-m4v", "video/mp4"); + mimeTypeMap->add("video/x-quicktime", "video/quicktime"); + mimeTypeMap->add("application/java", "application/java-archive"); + mimeTypeMap->add("application/x-java-archive", "application/java-archive"); + mimeTypeMap->add("application/x-zip-compressed", "application/zip"); + + return *mimeTypeMap; +} + +static HashSet<String>* s_supportedObjectMIMETypes; + +WebSettingsPrivate::WebSettingsPrivate() + : impl(0) + , delegate(0) + , sender(0) + , copyOnWrite(true) +{ +} + +WebSettings::WebSettings() +{ + m_private = new WebSettingsPrivate(); +} + +WebSettings::WebSettings(const WebSettings& otherSettings) +{ + m_private->impl = otherSettings.m_private->impl; +} + +WebSettings::~WebSettings() +{ + if (!m_private->copyOnWrite) { + delete m_private->impl; + m_private->impl = 0; + } + delete m_private; + m_private = 0; +} + +void WebSettings::setDelegate(WebSettingsDelegate* delegate) +{ + m_private->delegate = delegate; + m_private->sender = this; +} + +WebSettingsDelegate* WebSettings::delegate() +{ + return m_private->delegate; +} + +WebSettings* WebSettings::createFromStandardSettings(WebSettingsDelegate* delegate) +{ + WebSettings* settings = new WebSettings(); + settings->m_private->impl = standardSettings()->m_private->impl; + settings->m_private->delegate = delegate; + settings->m_private->sender = settings; + if (delegate) + delegate->didChangeSettings(settings); + + return settings; +} + +WebSettings* WebSettings::standardSettings() +{ + static WebSettings *settings = 0; + if (settings) + return settings; + + settings = new WebSettings; + settings->m_private->impl = new WebSettingsPrivate::WebSettingsPrivateImpl(); + settings->m_private->copyOnWrite = false; + settings->m_private->setUnsigned(BlackBerryBackgroundColor, WebCore::Color::white); + settings->m_private->setBoolean(BlackBerryCookiesEnabled, true); + settings->m_private->setDouble(BlackBerryInitialScale, -1); + settings->m_private->setUnsigned(BlackBerryMaxPluginInstances, 1); + settings->m_private->setUnsigned(BlackBerryOverZoomColor, WebCore::Color::white); + settings->m_private->setBoolean(BlackBerryScrollbarsEnabled, true); + + // FIXME: We should detect whether we are embedded in a browser or an email client and default to TextReflowEnabledOnlyForBlockZoom and TextReflowEnabled, respectively. + settings->m_private->setTextReflowMode(BlackBerryTextReflowMode, TextReflowDisabled); + + settings->m_private->setBoolean(BlackBerryUserScalableEnabled, true); + settings->m_private->setBoolean(BlackBerryUseWebKitCache, true); + settings->m_private->setBoolean(BlackBerryZoomToFitOnLoadEnabled, true); + settings->m_private->setInteger(WebKitDefaultFontSize, 16); + settings->m_private->setInteger(WebKitDefaultFixedFontSize, 13); + settings->m_private->setInteger(WebKitMinimumFontSize, 8); + settings->m_private->setString(WebKitDefaultTextEncodingName, "iso-8859-1"); + settings->m_private->setInteger(WebKitFirstScheduledLayoutDelay, 250); // Match Document::cLayoutScheduleThreshold. + settings->m_private->setBoolean(WebKitJavaScriptEnabled, true); + settings->m_private->setBoolean(WebKitLoadsImagesAutomatically, true); + settings->m_private->setBoolean(WebKitDownloadableBinaryFontsEnabled, true); + settings->m_private->setUnsignedLongLong(WebKitLocalStorageQuota, 5 * 1024 * 1024); + settings->m_private->setInteger(WebKitMaximumPagesInCache, 0); + settings->m_private->setBoolean(WebKitWebSocketsEnabled, true); + settings->m_private->setString(WebKitFixedFontFamily, "Courier New"); + settings->m_private->setString(WebKitSansSeriffFontFamily, "Arial"); + settings->m_private->setString(WebKitSeriffFontFamily, "Times New Roman"); + settings->m_private->setString(WebKitStandardFontFamily, "Times New Roman"); + settings->m_private->setBoolean(SpatialNavigationEnabled, false); + + return settings; +} + +void WebSettings::addSupportedObjectPluginMIMEType(const char* type) +{ + if (!s_supportedObjectMIMETypes) + s_supportedObjectMIMETypes = new HashSet<String>; + + s_supportedObjectMIMETypes->add(type); +} + +bool WebSettings::isSupportedObjectMIMEType(const WebString& mimeType) +{ + if (mimeType.isEmpty()) + return false; + + if (!s_supportedObjectMIMETypes) + return false; + + return s_supportedObjectMIMETypes->contains(getNormalizedMIMEType(mimeType)); +} + +WebString WebSettings::getNormalizedMIMEType(const WebString& type) +{ + MIMETypeAssociationMap::const_iterator i = mimeTypeAssociationMap().find(type); + + return i == mimeTypeAssociationMap().end() ? type : i->second; +} + +bool WebSettings::xssAuditorEnabled() const +{ + return m_private->getBoolean(WebKitXSSAuditorEnabled); +} + +void WebSettings::setXSSAuditorEnabled(bool enabled) +{ + return m_private->setBoolean(WebKitXSSAuditorEnabled, enabled); +} + +bool WebSettings::loadsImagesAutomatically() const +{ + return m_private->getBoolean(WebKitLoadsImagesAutomatically); +} + +void WebSettings::setLoadsImagesAutomatically(bool enabled) +{ + m_private->setBoolean(WebKitLoadsImagesAutomatically, enabled); +} + +bool WebSettings::downloadableBinaryFontsEnabled() const +{ + return m_private->getBoolean(WebKitDownloadableBinaryFontsEnabled); +} + +void WebSettings::setDownloadableBinaryFontsEnabled(bool enabled) +{ + return m_private->setBoolean(WebKitDownloadableBinaryFontsEnabled, enabled); +} + +bool WebSettings::shouldDrawBorderWhileLoadingImages() const +{ + return m_private->getBoolean(BlackBerryDrawBorderWhileLoadingImages); +} + +void WebSettings::setShouldDrawBorderWhileLoadingImages(bool enabled) +{ + m_private->setBoolean(BlackBerryDrawBorderWhileLoadingImages, enabled); +} + +bool WebSettings::isJavaScriptEnabled() const +{ + return m_private->getBoolean(WebKitJavaScriptEnabled); +} + +void WebSettings::setJavaScriptEnabled(bool enabled) +{ + m_private->setBoolean(WebKitJavaScriptEnabled, enabled); +} + +bool WebSettings::isPrivateBrowsingEnabled() const +{ + return m_private->getBoolean(WebKitPrivateBrowsingEnabled); +} + +void WebSettings::setPrivateBrowsingEnabled(bool enabled) +{ + m_private->setBoolean(WebKitPrivateBrowsingEnabled, enabled); +} + +int WebSettings::defaultFixedFontSize() const +{ + return m_private->getInteger(WebKitDefaultFixedFontSize); +} + +void WebSettings::setDefaultFixedFontSize(int defaultFixedFontSize) +{ + m_private->setInteger(WebKitDefaultFixedFontSize, defaultFixedFontSize); +} + +int WebSettings::defaultFontSize() const +{ + return m_private->getInteger(WebKitDefaultFontSize); +} + +void WebSettings::setDefaultFontSize(int defaultFontSize) +{ + m_private->setInteger(WebKitDefaultFontSize, defaultFontSize); +} + +int WebSettings::minimumFontSize() const +{ + return m_private->getInteger(WebKitMinimumFontSize); +} + +void WebSettings::setMinimumFontSize(int minimumFontSize) +{ + m_private->setInteger(WebKitMinimumFontSize, minimumFontSize); +} + +WebString WebSettings::serifFontFamily() const +{ + return m_private->getString(WebKitSeriffFontFamily); +} + +void WebSettings::setSerifFontFamily(const char* seriffFontFamily) +{ + m_private->setString(WebKitSeriffFontFamily, seriffFontFamily); +} + +WebString WebSettings::fixedFontFamily() const +{ + return m_private->getString(WebKitFixedFontFamily); +} + +void WebSettings::setFixedFontFamily(const char* fixedFontFamily) +{ + m_private->setString(WebKitFixedFontFamily, fixedFontFamily); +} + +WebString WebSettings::sansSerifFontFamily() const +{ + return m_private->getString(WebKitSansSeriffFontFamily); +} + +void WebSettings::setSansSerifFontFamily(const char* sansSeriffFontFamily) +{ + m_private->setString(WebKitSansSeriffFontFamily, sansSeriffFontFamily); +} + +WebString WebSettings::standardFontFamily() const +{ + return m_private->getString(WebKitStandardFontFamily); +} + +void WebSettings::setStandardFontFamily(const char* standardFontFamily) +{ + m_private->setString(WebKitStandardFontFamily, standardFontFamily); +} + +WebString WebSettings::userAgentString() const +{ + // FIXME: Is this the best place for this assertion. Why can't we just return an empty string + // and let the caller decide how to handle it? + + // The default user agent string is empty. We rely upon the client to set this for us. + // We check this by asserting if the client has not done so before the first time it is needed. + String userAgentString = m_private->getString(BlackBerryUserAgentString); + ASSERT(!userAgentString.isEmpty()); + return userAgentString; +} + +void WebSettings::setUserAgentString(const char* userAgentString) +{ + m_private->setString(BlackBerryUserAgentString, userAgentString); +} + +WebString WebSettings::defaultTextEncodingName() const +{ + return m_private->getString(WebKitDefaultTextEncodingName); +} + +void WebSettings::setDefaultTextEncodingName(const char* defaultTextEncodingName) +{ + m_private->setString(WebKitDefaultTextEncodingName, defaultTextEncodingName); +} + +bool WebSettings::isZoomToFitOnLoad() const +{ + return m_private->getBoolean(BlackBerryZoomToFitOnLoadEnabled); +} + +void WebSettings::setZoomToFitOnLoad(bool enabled) +{ + m_private->setBoolean(BlackBerryZoomToFitOnLoadEnabled, enabled); +} + +WebSettings::TextReflowMode WebSettings::textReflowMode() const +{ + return m_private->getTextReflowMode(BlackBerryTextReflowMode); +} + +void WebSettings::setTextReflowMode(TextReflowMode textReflowMode) +{ + m_private->setTextReflowMode(BlackBerryTextReflowMode, textReflowMode); +} + +bool WebSettings::isScrollbarsEnabled() const +{ + return m_private->getBoolean(BlackBerryScrollbarsEnabled); +} + +void WebSettings::setScrollbarsEnabled(bool enabled) +{ + m_private->setBoolean(BlackBerryScrollbarsEnabled, enabled); +} + +bool WebSettings::canJavaScriptOpenWindowsAutomatically() const +{ + return m_private->getBoolean(WebKitJavaScriptCanOpenWindowsAutomaticallyEnabled); +} + +void WebSettings::setJavaScriptOpenWindowsAutomatically(bool enabled) +{ + m_private->setBoolean(WebKitJavaScriptCanOpenWindowsAutomaticallyEnabled, enabled); +} + +bool WebSettings::arePluginsEnabled() const +{ + return m_private->getBoolean(WebKitPluginsEnabled); +} + +void WebSettings::setPluginsEnabled(bool enabled) +{ + m_private->setBoolean(WebKitPluginsEnabled, enabled); +} + +bool WebSettings::isGeolocationEnabled() const +{ + return m_private->getBoolean(WebKitGeolocationEnabled); +} + +void WebSettings::setGeolocationEnabled(bool enabled) +{ + m_private->setBoolean(WebKitGeolocationEnabled, enabled); +} + +bool WebSettings::doesGetFocusNodeContext() const +{ + return m_private->getBoolean(BlackBerryGetFocusNodeContextEnabled); +} + +void WebSettings::setGetFocusNodeContext(bool enabled) +{ + m_private->setBoolean(BlackBerryGetFocusNodeContextEnabled, enabled); +} + +WebString WebSettings::userStyleSheetString() const +{ + return m_private->getString(WebKitUserStyleSheet); +} + +void WebSettings::setUserStyleSheetString(const char* userStyleSheetString) +{ + // FIXME: This doesn't seem like the appropriate place to do this as WebSettings should ideally be a state store. + // Either the caller of this function should do this conversion or caller of the getter corresponding to this function + // should do this conversion. + + size_t length = strlen(userStyleSheetString); + Vector<char> data; + data.append(userStyleSheetString, length); + + Vector<char> encodedData; + WebCore::base64Encode(data, encodedData); + + const char prefix[] = "data:text/css;charset=utf-8;base64,"; + size_t prefixLength = sizeof(prefix) - 1; + Vector<char> dataURL; + dataURL.reserveCapacity(prefixLength + encodedData.size()); + dataURL.append(prefix, prefixLength); + dataURL.append(encodedData); + m_private->setString(WebKitUserStyleSheet, String(dataURL.data(), dataURL.size())); +} + +WebString WebSettings::userStyleSheetLocation() +{ + return m_private->getString(WebKitUserStyleSheetLocation); +} + +void WebSettings::setUserStyleSheetLocation(const char* userStyleSheetLocation) +{ + m_private->setString(WebKitUserStyleSheetLocation, userStyleSheetLocation); +} + +bool WebSettings::areLinksHandledExternally() const +{ + return m_private->getBoolean(BlackBerryLinksHandledExternallyEnabled); +} + +void WebSettings::setAreLinksHandledExternally(bool enabled) +{ + m_private->setBoolean(BlackBerryLinksHandledExternallyEnabled, enabled); +} + +void WebSettings::setAllowCrossSiteRequests(bool allow) +{ + m_private->setBoolean(BlackBerryAllowCrossSiteRequests, allow); +} + +bool WebSettings::allowCrossSiteRequests() const +{ + return m_private->getBoolean(BlackBerryAllowCrossSiteRequests); +} + +bool WebSettings::isUserScalable() const +{ + return m_private->getBoolean(BlackBerryUserScalableEnabled); +} + +void WebSettings::setUserScalable(bool enabled) +{ + m_private->setBoolean(BlackBerryUserScalableEnabled, enabled); +} + +int WebSettings::viewportWidth() const +{ + return m_private->getInteger(BlackBerryViewportWidth); +} + +void WebSettings::setViewportWidth(int width) +{ + m_private->setInteger(BlackBerryViewportWidth, width); +} + +double WebSettings::initialScale() const +{ + return m_private->getDouble(BlackBerryInitialScale); +} + +void WebSettings::setInitialScale(double initialScale) +{ + m_private->setDouble(BlackBerryInitialScale, initialScale); +} + +int WebSettings::firstScheduledLayoutDelay() const +{ + return m_private->getInteger(WebKitFirstScheduledLayoutDelay); +} + +void WebSettings::setFirstScheduledLayoutDelay(int delay) +{ + m_private->setInteger(WebKitFirstScheduledLayoutDelay, delay); +} + +// Whether to include pattern: in the list of string patterns. +bool WebSettings::shouldHandlePatternUrls() const +{ + return m_private->getBoolean(BlackBerryHandlePatternURLs); +} + +void WebSettings::setShouldHandlePatternUrls(bool handlePatternURLs) +{ + m_private->setBoolean(BlackBerryHandlePatternURLs, handlePatternURLs); +} + +bool WebSettings::areCookiesEnabled() const +{ + return m_private->getBoolean(BlackBerryCookiesEnabled); +} + +void WebSettings::setAreCookiesEnabled(bool enable) +{ + m_private->setBoolean(BlackBerryCookiesEnabled, enable); +} + +bool WebSettings::isLocalStorageEnabled() const +{ + return m_private->getBoolean(WebKitLocalStorageEnabled); +} + +void WebSettings::setIsLocalStorageEnabled(bool enable) +{ + m_private->setBoolean(WebKitLocalStorageEnabled, enable); +} + +bool WebSettings::isDatabasesEnabled() const +{ + return m_private->getBoolean(WebKitDatabasesEnabled); +} + +void WebSettings::setIsDatabasesEnabled(bool enable) +{ + m_private->setBoolean(WebKitDatabasesEnabled, enable); +} + +bool WebSettings::isAppCacheEnabled() const +{ + return m_private->getBoolean(WebKitOfflineWebApplicationCacheEnabled); +} + +void WebSettings::setIsAppCacheEnabled(bool enable) +{ + m_private->setBoolean(WebKitOfflineWebApplicationCacheEnabled, enable); +} + +unsigned long long WebSettings::localStorageQuota() const +{ + return m_private->getUnsignedLongLong(WebKitLocalStorageQuota); +} + +void WebSettings::setLocalStorageQuota(unsigned long long quota) +{ + m_private->setUnsignedLongLong(WebKitLocalStorageQuota, quota); +} + +int WebSettings::maximumPagesInCache() const +{ + // FIXME: We shouldn't be calling into WebCore from here. This class should just be a state store. + return WebCore::pageCache()->capacity(); +} + +void WebSettings::setMaximumPagesInCache(int pages) +{ + // FIXME: We shouldn't be calling into WebCore from here. This class should just be a state store. + unsigned realPages = std::max(0, pages); + WebCore::pageCache()->setCapacity(realPages); + m_private->setUnsigned(WebKitMaximumPagesInCache, realPages); +} + +WebString WebSettings::localStoragePath() const +{ + return m_private->getString(WebKitLocalStoragePath); +} + +void WebSettings::setLocalStoragePath(const WebString& path) +{ + m_private->setString(WebKitLocalStoragePath, path); +} + +WebString WebSettings::databasePath() const +{ + return m_private->getString(WebKitDatabasePath); +} + +void WebSettings::setDatabasePath(const WebString& path) +{ + m_private->setString(WebKitDatabasePath, path); +} + +WebString WebSettings::appCachePath() const +{ + return m_private->getString(WebKitOfflineWebApplicationCachePath); +} + +void WebSettings::setAppCachePath(const WebString& path) +{ + m_private->setString(WebKitOfflineWebApplicationCachePath, path); +} + +WebString WebSettings::pageGroupName() const +{ + return m_private->getString(WebKitPageGroupName); +} + +void WebSettings::setPageGroupName(const WebString& pageGroupName) +{ + m_private->setString(WebKitPageGroupName, pageGroupName); +} + +bool WebSettings::isEmailMode() const +{ + return m_private->getBoolean(BlackBerryEmailModeEnabled); +} + +void WebSettings::setEmailMode(bool enable) +{ + m_private->setBoolean(BlackBerryEmailModeEnabled, enable); +} + +bool WebSettings::shouldRenderAnimationsOnScrollOrZoom() const +{ + return m_private->getBoolean(BlackBerryRenderAnimationsOnScrollOrZoomEnabled); +} + +void WebSettings::setShouldRenderAnimationsOnScrollOrZoom(bool enable) +{ + m_private->setBoolean(BlackBerryRenderAnimationsOnScrollOrZoomEnabled, enable); +} + +unsigned WebSettings::overZoomColor() const +{ + return m_private->getUnsigned(BlackBerryOverZoomColor); +} + +void WebSettings::setOverZoomColor(unsigned color) +{ + m_private->setUnsigned(BlackBerryOverZoomColor, color); +} + +unsigned WebSettings::backgroundColor() const +{ + return m_private->getUnsigned(BlackBerryBackgroundColor); +} + +void WebSettings::setBackgroundColor(unsigned color) +{ + m_private->setUnsigned(BlackBerryBackgroundColor, color); +} + +bool WebSettings::isWritingDirectionRTL() const +{ + return m_private->getBoolean(BlackBerryUseRTLWritingDirection); +} + +void WebSettings::setWritingDirectionRTL(bool useRTLWritingDirection) +{ + m_private->setBoolean(BlackBerryUseRTLWritingDirection, useRTLWritingDirection); +} + +bool WebSettings::useWebKitCache() const +{ + return m_private->getBoolean(BlackBerryUseWebKitCache); +} + +void WebSettings::setUseWebKitCache(bool useWebKitCache) +{ + m_private->setBoolean(BlackBerryUseWebKitCache, useWebKitCache); +} + +bool WebSettings::isFrameFlatteningEnabled() const +{ + return m_private->getBoolean(WebKitFrameFlatteningEnabled); +} + +void WebSettings::setFrameFlatteningEnabled(bool enable) +{ + m_private->setBoolean(WebKitFrameFlatteningEnabled, enable); +} + +bool WebSettings::isDirectRenderingToWindowEnabled() const +{ + return m_private->getBoolean(BlackBerryDirectRenderingToWindowEnabled); +} + +void WebSettings::setDirectRenderingToWindowEnabled(bool enable) +{ + m_private->setBoolean(BlackBerryDirectRenderingToWindowEnabled, enable); +} + +unsigned WebSettings::maxPluginInstances() const +{ + return m_private->getUnsigned(BlackBerryMaxPluginInstances); +} + +void WebSettings::setMaxPluginInstances(unsigned maxPluginInstances) +{ + m_private->setUnsigned(BlackBerryMaxPluginInstances, maxPluginInstances); +} + +bool WebSettings::areWebSocketsEnabled() const +{ + return m_private->getBoolean(WebKitWebSocketsEnabled); +} + +void WebSettings::setWebSocketsEnabled(bool enable) +{ + m_private->setBoolean(WebKitWebSocketsEnabled, enable); +} + +bool WebSettings::isSpatialNavigationEnabled() const +{ + return m_private->getBoolean(SpatialNavigationEnabled); +} + +void WebSettings::setSpatialNavigationEnabled(bool enable) +{ + m_private->setBoolean(SpatialNavigationEnabled, enable); +} + +} // namespace WebKit +} // namespace BlackBerry diff --git a/Source/WebKit/blackberry/Api/WebSettings.h b/Source/WebKit/blackberry/Api/WebSettings.h new file mode 100644 index 000000000..403e8f4a2 --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebSettings.h @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef WebSettings_h +#define WebSettings_h + +#include "BlackBerryGlobal.h" + +namespace BlackBerry { +namespace WebKit { + +class WebSettings; +class WebSettingsPrivate; + +/*! + @struct WebSettingsDelegate + Defines the methods that must be implemented by a delegate of WebSettings. +*/ +struct BLACKBERRY_EXPORT WebSettingsDelegate { + virtual ~WebSettingsDelegate() { } + + /*! + Sent when the value of a setting changed as well as on instantiation of a WebSettings object. + @param settings The WebSettings object that sent the message. + */ + virtual void didChangeSettings(WebSettings*) = 0; +}; + +/*! + @class WebSettings +*/ +class BLACKBERRY_EXPORT WebSettings { +public: + static WebSettings* createFromStandardSettings(WebSettingsDelegate* = 0); + ~WebSettings(); + + static WebSettings* standardSettings(); + + void setDelegate(WebSettingsDelegate*); + WebSettingsDelegate* delegate(); + + static void addSupportedObjectPluginMIMEType(const char*); + static bool isSupportedObjectMIMEType(const WebString&); + static WebString getNormalizedMIMEType(const WebString&); + + bool xssAuditorEnabled() const; + void setXSSAuditorEnabled(bool); + + bool loadsImagesAutomatically() const; + void setLoadsImagesAutomatically(bool); + + bool shouldDrawBorderWhileLoadingImages() const; + void setShouldDrawBorderWhileLoadingImages(bool); + + bool isJavaScriptEnabled() const; + void setJavaScriptEnabled(bool); + + bool isPrivateBrowsingEnabled() const; + void setPrivateBrowsingEnabled(bool); + + int defaultFixedFontSize() const; + void setDefaultFixedFontSize(int); + + int defaultFontSize() const; + void setDefaultFontSize(int); + + int minimumFontSize() const; + void setMinimumFontSize(int); + + WebString serifFontFamily() const; + void setSerifFontFamily(const char*); + WebString fixedFontFamily() const; + void setFixedFontFamily(const char*); + WebString sansSerifFontFamily() const; + void setSansSerifFontFamily(const char*); + WebString standardFontFamily() const; + void setStandardFontFamily(const char*); + + void setDownloadableBinaryFontsEnabled(bool); + bool downloadableBinaryFontsEnabled() const; + + WebString userAgentString() const; + void setUserAgentString(const char*); + + WebString defaultTextEncodingName() const; + void setDefaultTextEncodingName(const char*); + + bool isZoomToFitOnLoad() const; + void setZoomToFitOnLoad(bool); + + enum TextReflowMode { TextReflowDisabled, TextReflowEnabled, TextReflowEnabledOnlyForBlockZoom }; + TextReflowMode textReflowMode() const; + void setTextReflowMode(TextReflowMode); + + bool isScrollbarsEnabled() const; + void setScrollbarsEnabled(bool); + + // FIXME: Consider renaming this method upstream, where it is called javaScriptCanOpenWindowsAutomatically. + bool canJavaScriptOpenWindowsAutomatically() const; + void setJavaScriptOpenWindowsAutomatically(bool); + + bool arePluginsEnabled() const; + void setPluginsEnabled(bool); + + bool isGeolocationEnabled() const; + void setGeolocationEnabled(bool); + + // Context info + bool doesGetFocusNodeContext() const; + void setGetFocusNodeContext(bool); + + WebString userStyleSheetString() const; + void setUserStyleSheetString(const char*); + + WebString userStyleSheetLocation(); + void setUserStyleSheetLocation(const char*); + + // External link handlers + bool areLinksHandledExternally() const; + void setAreLinksHandledExternally(bool); + + // BrowserField2 settings + void setAllowCrossSiteRequests(bool); + bool allowCrossSiteRequests() const; + bool isUserScalable() const; + void setUserScalable(bool); + int viewportWidth() const; + void setViewportWidth(int); + double initialScale() const; + void setInitialScale(double); + + int firstScheduledLayoutDelay() const; + void setFirstScheduledLayoutDelay(int); + + // Whether to include pattern: in the list of string patterns. + bool shouldHandlePatternUrls() const; + void setShouldHandlePatternUrls(bool); + + bool areCookiesEnabled() const; + void setAreCookiesEnabled(bool); + + // Web storage settings + bool isLocalStorageEnabled() const; + void setIsLocalStorageEnabled(bool); + + bool isDatabasesEnabled() const; + void setIsDatabasesEnabled(bool); + + bool isAppCacheEnabled() const; + void setIsAppCacheEnabled(bool); + + unsigned long long localStorageQuota() const; + void setLocalStorageQuota(unsigned long long); + + // Page cache + void setMaximumPagesInCache(int); + int maximumPagesInCache() const; + + WebString localStoragePath() const; + void setLocalStoragePath(const WebString&); + + WebString databasePath() const; + void setDatabasePath(const WebString&); + + WebString appCachePath() const; + void setAppCachePath(const WebString&); + + WebString pageGroupName() const; + void setPageGroupName(const WebString&); + + // FIXME: We shouldn't have an email mode. Instead, we should expose all email-related settings + // so that the email client can toggle them directly. + bool isEmailMode() const; + void setEmailMode(bool enable); + + bool shouldRenderAnimationsOnScrollOrZoom() const; + void setShouldRenderAnimationsOnScrollOrZoom(bool enable); + + unsigned overZoomColor() const; + void setOverZoomColor(unsigned); + + unsigned backgroundColor() const; + void setBackgroundColor(unsigned); + + bool isWritingDirectionRTL() const; + void setWritingDirectionRTL(bool); + + bool useWebKitCache() const; + void setUseWebKitCache(bool); + + bool isFrameFlatteningEnabled() const; + void setFrameFlatteningEnabled(bool); + + bool isDirectRenderingToWindowEnabled() const; + void setDirectRenderingToWindowEnabled(bool); + + unsigned maxPluginInstances() const; + void setMaxPluginInstances(unsigned num); + + bool areWebSocketsEnabled() const; + void setWebSocketsEnabled(bool); + + bool isSpatialNavigationEnabled() const; + void setSpatialNavigationEnabled(bool); + +private: + WebSettingsPrivate* m_private; + WebSettings(); + WebSettings(const WebSettings&); +}; + +/*! + @class WebSettingsTransaction + Defines a scope guard that suppresses didChangeSettings messages within its scope. + On destruction the guarded WebSettings object will dispatch exactly one didChangeSettings message. +*/ +class BLACKBERRY_EXPORT WebSettingsTransaction { +public: + WebSettingsTransaction(WebSettings* settings) + : m_settings(settings) + , m_savedDelegate(0) + { + if (!settings) + return; + m_savedDelegate = settings->delegate(); + settings->setDelegate(0); + } + + ~WebSettingsTransaction() + { + if (!m_settings || !m_savedDelegate) + return; + m_settings->setDelegate(m_savedDelegate); + m_savedDelegate->didChangeSettings(m_settings); + } + +private: + WebSettingsTransaction(const WebSettingsTransaction&); + WebSettingsTransaction& operator=(const WebSettingsTransaction&); + + WebSettings* m_settings; + WebSettingsDelegate* m_savedDelegate; +}; + +} // namespace WebKit +} // namespace BlackBerry + +#endif // WebSettings_h diff --git a/Source/WebKit/blackberry/Api/WebSettings_p.h b/Source/WebKit/blackberry/Api/WebSettings_p.h new file mode 100644 index 000000000..7f9e2334d --- /dev/null +++ b/Source/WebKit/blackberry/Api/WebSettings_p.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef WebSettings_p_h +#define WebSettings_p_h + +#include "WebSettings.h" + +#include <wtf/HashMap.h> +#include <wtf/text/StringHash.h> + +#define synthesizeAccessorsForPrimitiveValuePrefixAndType(prefix, type) \ + void set##prefix(const String& key, type newValue) { \ + ASSERT(impl); \ + if (get##prefix(key) == newValue) \ + return; \ + if (copyOnWrite) { \ + copyOnWrite = false; \ + impl = new WebSettingsPrivateImpl(*impl); \ + } \ + PrimitiveValue primitiveValue; \ + primitiveValue.prefix##Value = newValue; \ + impl->primitiveValues.set(key, primitiveValue); \ + if (delegate) \ + delegate->didChangeSettings(sender); \ + } \ + type get##prefix(const String& key) const { \ + ASSERT(impl); \ + if (!impl->primitiveValues.contains(key)) \ + return static_cast<type>(false); \ + return impl->primitiveValues.get(key).prefix##Value; \ + } + +namespace BlackBerry { +namespace WebKit { + +struct WebSettingsPrivate { + union PrimitiveValue { + WebSettings::TextReflowMode TextReflowModeValue; + bool BooleanValue; + double DoubleValue; + int IntegerValue; + unsigned UnsignedValue; + unsigned long long UnsignedLongLongValue; + }; + + struct WebSettingsPrivateImpl { + HashMap<String, PrimitiveValue> primitiveValues; + HashMap<String, String> stringValues; + }; + + WebSettingsPrivateImpl* impl; + WebSettingsDelegate* delegate; + WebSettings* sender; + bool copyOnWrite; + + WebSettingsPrivate(); + + synthesizeAccessorsForPrimitiveValuePrefixAndType(TextReflowMode, WebSettings::TextReflowMode); + + synthesizeAccessorsForPrimitiveValuePrefixAndType(Boolean, bool); + + synthesizeAccessorsForPrimitiveValuePrefixAndType(Double, double); + + synthesizeAccessorsForPrimitiveValuePrefixAndType(Integer, int); + + synthesizeAccessorsForPrimitiveValuePrefixAndType(Unsigned, unsigned); + + synthesizeAccessorsForPrimitiveValuePrefixAndType(UnsignedLongLong, unsigned long long); + + String getString(const String& key) const + { + ASSERT(impl); + if (!impl->stringValues.contains(key)) + return String(); + return impl->stringValues.get(key); + } + + void setString(const String& key, const String& newValue) + { + ASSERT(impl); + if (getString(key) == newValue) + return; + + if (copyOnWrite) { + copyOnWrite = false; + impl = new WebSettingsPrivateImpl(*impl); + } + + impl->stringValues.set(key, newValue); + if (delegate) + delegate->didChangeSettings(sender); + } +}; + +} // namespace WebKit +} // namespace BlackBerry + +#endif // WebSettings_p_h diff --git a/Source/WebKit/blackberry/Api/WebString.cpp b/Source/WebKit/blackberry/Api/WebString.cpp index 7429d86de..7fc9a1a77 100644 --- a/Source/WebKit/blackberry/Api/WebString.cpp +++ b/Source/WebKit/blackberry/Api/WebString.cpp @@ -19,7 +19,6 @@ #include "config.h" #include "WebString.h" -#include "WebStringImpl.h" #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> @@ -27,21 +26,21 @@ namespace BlackBerry { namespace WebKit { WebString::WebString(const char* latin1) - : m_impl(static_cast<WebStringImpl*>(WTF::StringImpl::create(latin1).releaseRef())) + : m_impl(StringImpl::create(latin1).leakRef()) { } WebString::WebString(const char* latin1, unsigned length) - : m_impl(static_cast<WebStringImpl*>(WTF::StringImpl::create(latin1, length).releaseRef())) + : m_impl(StringImpl::create(latin1, length).leakRef()) { } WebString::WebString(const unsigned short* utf16, unsigned length) - : m_impl(static_cast<WebStringImpl*>(WTF::StringImpl::create(utf16, length).releaseRef())) + : m_impl(StringImpl::create(utf16, length).leakRef()) { } -WebString::WebString(WebStringImpl* impl) +WebString::WebString(StringImpl* impl) : m_impl(impl) { if (m_impl) @@ -109,7 +108,7 @@ bool WebString::equal(const char* utf8) const bool WebString::equalIgnoringCase(const char* utf8) const { - return WTF::equalIgnoringCase(m_impl, utf8); + return WTF::equalIgnoringCase(utf8, WTF::String(m_impl)); } } // namespace WebKit diff --git a/Source/WebKit/blackberry/Api/WebString.h b/Source/WebKit/blackberry/Api/WebString.h index fe28bdef6..fe43c247f 100644 --- a/Source/WebKit/blackberry/Api/WebString.h +++ b/Source/WebKit/blackberry/Api/WebString.h @@ -22,11 +22,14 @@ #include "BlackBerryGlobal.h" #include <string> +// Not for public API purpose. +namespace WTF { +class StringImpl; +} + namespace BlackBerry { namespace WebKit { -class WebStringImpl; - class BLACKBERRY_EXPORT WebString { public: WebString() : m_impl(0) { } @@ -34,7 +37,6 @@ public: WebString(const char* latin1); WebString(const char* latin1, unsigned length); WebString(const unsigned short* utf16, unsigned length); - WebString(WebStringImpl*); WebString(const WebString&); WebString& operator=(const WebString&); std::string utf8() const; @@ -44,9 +46,13 @@ public: bool isEmpty() const; bool equal(const char* utf8) const; bool equalIgnoringCase(const char* utf8) const; - WebStringImpl* impl() const { return m_impl; } + + // Not for public API purpose. + WebString(WTF::StringImpl*); + WTF::StringImpl* impl() const { return m_impl; } + private: - WebStringImpl* m_impl; + WTF::StringImpl* m_impl; }; } // namespace WebKit } // namespace BlackBerry diff --git a/Source/WebKit/blackberry/ChangeLog b/Source/WebKit/blackberry/ChangeLog new file mode 100644 index 000000000..60d341ad0 --- /dev/null +++ b/Source/WebKit/blackberry/ChangeLog @@ -0,0 +1,390 @@ +2012-02-24 Shinya Kawanaka <shinyak@chromium.org> + + SpellCheckRequest needs to know the context where the spellcheck happened. + https://bugs.webkit.org/show_bug.cgi?id=79320 + + Reviewed by Hajime Morita. + + * WebCoreSupport/EditorClientBlackBerry.cpp: + (WebCore::EditorClientBlackBerry::requestCheckingOfString): + * WebCoreSupport/EditorClientBlackBerry.h: + (EditorClientBlackBerry): + +2012-02-24 Charles Wei <charles.wei@torchmobile.com.cn> + + [BlackBerry] Anchor mailto: with target set won't launch Messaging application when clicked + https://bugs.webkit.org/show_bug.cgi?id=79318 + + Need to give the client a chance to decide how to handle the new window request. + + Reviewed by Rob Buis. + + * WebCoreSupport/FrameLoaderClientBlackBerry.cpp: + (WebCore::FrameLoaderClientBlackBerry::dispatchDecidePolicyForNewWindowAction): + +2012-02-23 Mike Fenton <mifenton@rim.com> + + [BlackBerry] Selection handler has compile failure with logs enabled. + https://bugs.webkit.org/show_bug.cgi?id=79392 + + Reviewed by Antonio Gomes. + + Build Fix. Update log to avoid usage of toString which was removed. + + * WebKitSupport/SelectionHandler.cpp: + (BlackBerry::WebKit::SelectionHandler::selectionPositionChanged): + +2012-02-19 Antonio Gomes <agomes@rim.com> + + Fat fingers - Add a clearer way to distinguish the node we want (shadow or non-shadow) + https://bugs.webkit.org/show_bug.cgi?id=79256 + PR #127814 / MKS_2587410 + + Reviewed by Rob Buis. + + Patch adds a cleaner way for call sites of FatFingersResult to + query for the appropriated target node: shadow or non-shadow DOM nodes. + + It also renames FatFingersResults::validNode to ::node, assuming + that "invalid" nodes are not applicable in any context. + + * Api/WebPage.cpp: + (BlackBerry::WebKit::WebPagePrivate::clearDocumentData): + (BlackBerry::WebKit::WebPagePrivate::contextNode): + (BlackBerry::WebKit::WebPagePrivate::handleMouseEvent): + * WebKitSupport/FatFingers.h: + (FatFingersResult): + (BlackBerry::WebKit::FatFingersResult::node): + (BlackBerry::WebKit::FatFingersResult::nodeAsElementIfApplicable): + * WebKitSupport/SelectionHandler.cpp: + (BlackBerry::WebKit::SelectionHandler::selectAtPoint): + * WebKitSupport/TouchEventHandler.cpp: + (BlackBerry::WebKit::TouchEventHandler::touchHoldEvent): + (BlackBerry::WebKit::TouchEventHandler::handleTouchPoint): + +2012-02-23 Jacky Jiang <zhajiang@rim.com> + + [BlackBerry] Upstream BlackBerry API web page related files + https://bugs.webkit.org/show_bug.cgi?id=74380 + + Reviewed by Antonio Gomes. + + Initial upstream, no new tests. + + * Api/WebPage.cpp: Added. + * Api/WebPage.h: Added. + * Api/WebPage_p.h: Added. + +2012-02-23 Leo Yang <leo.yang@torchmobile.com.cn> + + [BlackBerry] Remove unused ChromeClientBlackBerry::platformCompositingWindow(), platformWindow() and WebPageClient::compositingWindow() + https://bugs.webkit.org/show_bug.cgi?id=78681 + + Reviewed by Antonio Gomes. + + * Api/WebPageClient.h: + * WebCoreSupport/ChromeClientBlackBerry.cpp: + (WebCore): + * WebCoreSupport/ChromeClientBlackBerry.h: + (ChromeClientBlackBerry): + +2012-02-23 Leo Yang <leo.yang@torchmobile.com.cn> + + [BlackBerry] Upstream GLES2Context.{h, cpp} + https://bugs.webkit.org/show_bug.cgi?id=79196 + + Reviewed by Rob Buis. + + Initial upstream, no new tests. + + * WebKitSupport/GLES2Context.cpp: Added. + * WebKitSupport/GLES2Context.h: Added. + +2012-02-23 Mike Fenton <mifenton@rim.com> + + [BlackBerry] InputHandler requires cleanup of Navigation Mode handling. + https://bugs.webkit.org/show_bug.cgi?id=79366 + + Reviewed by Rob Buis. + + Cleanup InputHandler navigation based code. + + 1) Remove the concept of NavigationMode and replace it + with simple showKeyboard calls. + + 2) Remove navigation move events and replace with standard + key events. + + 3) Standardize function/variable names and remove obsolete + functions. + + * Api/WebPageClient.h: + * WebKitSupport/InputHandler.cpp: + (BlackBerry::WebKit::InputHandler::InputHandler): + (BlackBerry::WebKit::InputHandler::nodeFocused): + (BlackBerry::WebKit::InputHandler::setElementUnfocused): + (BlackBerry::WebKit::InputHandler::setElementFocused): + (BlackBerry::WebKit::InputHandler::ensureFocusTextElementVisible): + (BlackBerry::WebKit::InputHandler::setDelayKeyboardVisibilityChange): + (BlackBerry::WebKit::InputHandler::processPendingKeyboardVisibilityChange): + (BlackBerry::WebKit::InputHandler::notifyClientOfKeyboardVisibilityChange): + * WebKitSupport/InputHandler.h: + (InputHandler): + * WebKitSupport/SelectionHandler.cpp: + (BlackBerry::WebKit::SelectionHandler::setCaretPosition): + (BlackBerry::WebKit::SelectionHandler::updateOrHandleInputSelection): + * WebKitSupport/TouchEventHandler.cpp: + (BlackBerry::WebKit::TouchEventHandler::touchEventCancel): + (BlackBerry::WebKit::TouchEventHandler::handleTouchPoint): + +2012-02-21 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/EditorClientBlackBerry.cpp: + (WebCore::EditorClientBlackBerry::shouldApplyStyle): + * WebCoreSupport/EditorClientBlackBerry.h: + (EditorClientBlackBerry): + +2012-02-22 Mike Fenton <mifenton@rim.com> + + [BlackBerry] InputHandler has signed vs unsigned comparison. + https://bugs.webkit.org/show_bug.cgi?id=79261 + + Fix warning by casting the unsigned int to an int. + + Reviewed by Rob Buis. + + * WebKitSupport/InputHandler.cpp: + (BlackBerry::WebKit::InputHandler::rectForCaret): + +2012-02-22 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/EditorClientBlackBerry.cpp: + (WebCore::EditorClientBlackBerry::shouldApplyStyle): + * WebCoreSupport/EditorClientBlackBerry.h: + (EditorClientBlackBerry): + +2012-02-18 Antonio Gomes <agomes@rim.com> + + Fat fingers - cache the first rect-based hit test so we do not need to do it again + https://bugs.webkit.org/show_bug.cgi?id=79115 + + Reviewed by Adam Treat. + + Our FatFingers implementation runs currently in two phases: + the first checks for the elements intrinsically clickable; + the second checks for elements made clickable by the page + (for example, a div with a onclick event listener attached to it). + For each phase, we perform a rect hittest, which is not needed since + the result of each is the same. + + Patch introduces a caching mechanism so we avoid on rect hittest: + when the first phase runs, it caches each nodeset per document in + a hashmap. This second phase works with the cached results. + + No behavioral change, but performance is better since we + avoid one (possibly expensive) rect hittest. + + I measured the performance gain on https://www.kvd.se/, and we + save up to 0.04 seconds, by caching and re-using the results. + + * WebKitSupport/FatFingers.cpp: + (BlackBerry::WebKit::dumpHitTestResult): + (BlackBerry::WebKit::FatFingers::findBestPoint): + (BlackBerry::WebKit::FatFingers::findIntersectingRegions): + (BlackBerry::WebKit::FatFingers::cachingStrategy): + (WebKit): + (BlackBerry::WebKit::FatFingers::getNodesFromRect): + * WebKitSupport/FatFingers.h: + +2012-02-20 Antonio Gomes <agomes@rim.com> + + All default video/audio control elements should be rect-hit testable (Part II) + PR #139518 / MKS_3005538 + + Reviewed by George Staikos. + + Add HTMLInputElement::isMediaControlElement as a criteria + to consider a element as clickable. + + Note that is should be only used while in the "ClickableByDefault" + phase of FatFingers. + + * WebKitSupport/FatFingers.cpp: + (BlackBerry::WebKit::FatFingers::isElementClickable): + +2012-02-16 Antonio Gomes <agomes@rim.com> + + [BlackBerry] Implemented a way to defer client navigation change client notifications + https://bugs.webkit.org/show_bug.cgi?id=78848 + + Reviewed by Rob Buis. + + Currently we postpone touch_down till touch_up if user touches + the screen and an input field has the WebKit focus. This is done + so we can scroll the page without hidding the vkb needlessly. + + However, it breaks the conversion of touch to mouse events + if an input field has the focus in the following scenario: + an <input type=text> is focused and an user grab and-drag + a <input type=range> knob/slide. It does not work until the + user unfocuses the currently focused edit field. + + Patch introduces a way to unfocus a currently focused input field, + without requesting the client to show or hide the virtual keyboard + right way. Instead it gets a delayed notification of the vkb mode requested + at either touch_released/mouse_up or touch_cancel time. + + For now, due to content side issues with major web sites, + only delay navigation mode notification changes if we are not dealing with + input modes. + + * WebKitSupport/InputHandler.cpp: + (BlackBerry::WebKit::InputHandler::InputHandler): + (BlackBerry::WebKit::InputHandler::nodeFocused): + (BlackBerry::WebKit::InputHandler::setElementFocused): + (BlackBerry::WebKit::InputHandler::setNavigationMode): + (WebKit): + (BlackBerry::WebKit::InputHandler::setDelayClientNotificationOfNavigationModeChange): + (BlackBerry::WebKit::InputHandler::processPendingClientNavigationModeChangeNotification): + (BlackBerry::WebKit::InputHandler::notifyClientOfNavigationModeChange): + (BlackBerry::WebKit::InputHandler::willOpenPopupForNode): + (BlackBerry::WebKit::InputHandler::setPopupListIndexes): + (BlackBerry::WebKit::InputHandler::spannableTextInRange): + (BlackBerry::WebKit::InputHandler::removeComposedText): + (BlackBerry::WebKit::InputHandler::firstSpanInString): + (BlackBerry::WebKit::InputHandler::setText): + (BlackBerry::WebKit::InputHandler::setRelativeCursorPosition): + * WebKitSupport/InputHandler.h: + (InputHandler): + +2012-02-16 Antonio Gomes <agomes@rim.com> + + Crash @WebPagePrivate::enqueueRenderingOfClippedContentOfScrollableNodeAfterInRegionScrolling MKS_2986818 + https://bugs.webkit.org/show_bug.cgi?id=78845 + + Reviewed by Rob Buis. + + We were trying to operate on a cached Node when its page/frame/document + were gone to PageCache already. To avoid such problems, lets clean up + any document data we have cached when the Frame goes into the cache. + + * WebCoreSupport/FrameLoaderClientBlackBerry.cpp: + (WebCore::FrameLoaderClientBlackBerry::didSaveToPageCache): + (WebCore): + * WebCoreSupport/FrameLoaderClientBlackBerry.h: + (FrameLoaderClientBlackBerry): + +2012-02-16 Antonio Gomes <agomes@rim.com> + + [BlackBerry] Upstream touch handling related classes + https://bugs.webkit.org/show_bug.cgi?id=78509 + + Reviewed by Adam Treat and Rob Buis. + + FatFingers is the class responsible to the whole touch + accuracy of the BlackBerry port. Initial upstream. + + * WebKitSupport/FatFingers.cpp: Added. + (WebKit): + (BlackBerry::WebKit::FatFingers::fingerRectForPoint): + (BlackBerry::WebKit::hasMousePressListener): + (BlackBerry::WebKit::FatFingers::isElementClickable): + (BlackBerry::WebKit::isFieldWithText): + (BlackBerry::WebKit::distanceBetweenPoints): + (BlackBerry::WebKit::compareDistanceBetweenPoints): + (BlackBerry::WebKit::isValidFrameOwner): + (BlackBerry::WebKit::FatFingers::FatFingers): + (BlackBerry::WebKit::FatFingers::~FatFingers): + (BlackBerry::WebKit::FatFingers::findBestPoint): + (BlackBerry::WebKit::FatFingers::checkFingerIntersection): + (BlackBerry::WebKit::FatFingers::findIntersectingRegions): + (BlackBerry::WebKit::FatFingers::checkForClickableElement): + (BlackBerry::WebKit::FatFingers::checkForText): + (BlackBerry::WebKit::FatFingers::getPaddings): + (BlackBerry::WebKit::FatFingers::nodesFromRect): + (BlackBerry::WebKit::FatFingers::getRelevantInfoFromPoint): + (BlackBerry::WebKit::FatFingers::setSuccessfulFatFingersResult): + * WebKitSupport/FatFingers.h: Added. + (WebCore): + (WebKit): + (FatFingersResult): + (BlackBerry::WebKit::FatFingersResult::FatFingersResult): + (BlackBerry::WebKit::FatFingersResult::reset): + (BlackBerry::WebKit::FatFingersResult::originPosition): + (BlackBerry::WebKit::FatFingersResult::adjustedPosition): + (BlackBerry::WebKit::FatFingersResult::positionWasAdjusted): + (BlackBerry::WebKit::FatFingersResult::isTextInput): + (BlackBerry::WebKit::FatFingersResult::isValid): + (BlackBerry::WebKit::FatFingersResult::validNode): + (BlackBerry::WebKit::FatFingersResult::nodeAsElementIfApplicable): + (FatFingers): + +2012-02-16 Antonio Gomes <agomes@rim.com> + + [BlackBerry] Upstream touch handling related classes + https://bugs.webkit.org/show_bug.cgi?id=78509 + + Reviewed by Adam Treat. + + Initial upstream of the Blackberry specific single touch event + handler class. + + * blackberry/WebKitSupport/TouchEventHandler.cpp: Added. + (WebKit): + (BlackBerry::WebKit::hasMouseMoveListener): + (BlackBerry::WebKit::hasTouchListener): + (BlackBerry::WebKit::elementExpectsMouseEvents): + (BlackBerry::WebKit::shouldConvertTouchToMouse): + (BlackBerry::WebKit::TouchEventHandler::TouchEventHandler): + (BlackBerry::WebKit::TouchEventHandler::~TouchEventHandler): + (BlackBerry::WebKit::TouchEventHandler::shouldSuppressMouseDownOnTouchDown): + [BlackBerry] Upstream touch handling related classes + https://bugs.webkit.org/show_bug.cgi?id=78509 + + Reviewed by Rob Buis. + + InRegionScrollableArea specializes the BlackBerry specific ScrollViewBase, + working as a read-only wrapper object for a scrollable areas in the page. + It is used in our client side to control in-region scrolling (scrollable boxes, + inner frames, etc). + + Initial upstream. + + * WebKitSupport/InRegionScrollableArea.cpp: Added. + (WebKit): + (BlackBerry::WebKit::InRegionScrollableArea::InRegionScrollableArea): + (BlackBerry::WebKit::InRegionScrollableArea::calculateMinimumScrollPosition): + (BlackBerry::WebKit::InRegionScrollableArea::calculateMaximumScrollPosition): + (BlackBerry::WebKit::InRegionScrollableArea::layer): + (BlackBerry): + * WebKitSupport/InRegionScrollableArea.h: Added. + (WebCore): + (WebKit): + (InRegionScrollableArea): + +2012-02-16 Antonio Gomes <agomes@rim.com> + + (BlackBerry::WebKit::TouchEventHandler::touchEventCancel): + (BlackBerry::WebKit::TouchEventHandler::touchHoldEvent): + (BlackBerry::WebKit::TouchEventHandler::handleTouchPoint): + (BlackBerry::WebKit::TouchEventHandler::spellCheck): + (BlackBerry::WebKit::TouchEventHandler::handleFatFingerPressed): + (BlackBerry::WebKit::elementForTapHighlight): + (BlackBerry::WebKit::TouchEventHandler::drawTapHighlight): + * blackberry/WebKitSupport/TouchEventHandler.h: Added. + (WebCore): + (WebKit): + (TouchEventHandler): + (BlackBerry::WebKit::TouchEventHandler::lastFatFingersResult): + (BlackBerry::WebKit::TouchEventHandler::resetLastFatFingersResult): + diff --git a/Source/WebKit/blackberry/WebCoreSupport/ChromeClientBlackBerry.cpp b/Source/WebKit/blackberry/WebCoreSupport/ChromeClientBlackBerry.cpp index 0e9acffd8..b12f49b21 100644 --- a/Source/WebKit/blackberry/WebCoreSupport/ChromeClientBlackBerry.cpp +++ b/Source/WebKit/blackberry/WebCoreSupport/ChromeClientBlackBerry.cpp @@ -61,8 +61,10 @@ #include "WebSettings.h" #include "WebString.h" #include "WindowFeatures.h" + #include <BlackBerryPlatformLog.h> #include <BlackBerryPlatformSettings.h> +#include <BlackBerryPlatformWindow.h> #define DEBUG_OVERFLOW_DETECTION 0 @@ -830,14 +832,4 @@ bool ChromeClientBlackBerry::allowsAcceleratedCompositing() const } #endif -void* ChromeClientBlackBerry::platformWindow() const -{ - return m_webPagePrivate->m_client->window(); -} - -void* ChromeClientBlackBerry::platformCompositingWindow() const -{ - return m_webPagePrivate->m_client->compositingWindow(); -} - } // namespace WebCore diff --git a/Source/WebKit/blackberry/WebCoreSupport/ChromeClientBlackBerry.h b/Source/WebKit/blackberry/WebCoreSupport/ChromeClientBlackBerry.h index 76a715abe..99c8b6062 100644 --- a/Source/WebKit/blackberry/WebCoreSupport/ChromeClientBlackBerry.h +++ b/Source/WebKit/blackberry/WebCoreSupport/ChromeClientBlackBerry.h @@ -148,9 +148,6 @@ public: virtual bool allowsAcceleratedCompositing() const; #endif - virtual void* platformWindow() const; - virtual void* platformCompositingWindow() const; - BlackBerry::WebKit::WebPagePrivate* webPagePrivate() const { return m_webPagePrivate; } private: diff --git a/Source/WebKit/blackberry/WebCoreSupport/EditorClientBlackBerry.cpp b/Source/WebKit/blackberry/WebCoreSupport/EditorClientBlackBerry.cpp new file mode 100644 index 000000000..0e4441d82 --- /dev/null +++ b/Source/WebKit/blackberry/WebCoreSupport/EditorClientBlackBerry.cpp @@ -0,0 +1,628 @@ +/* + * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "EditorClientBlackBerry.h" + +#include "DOMSupport.h" +#include "DumpRenderTreeClient.h" +#include "EditCommand.h" +#include "Frame.h" +#include "HTMLInputElement.h" +#include "HTMLNames.h" +#include "InputHandler.h" +#include "KeyboardEvent.h" +#include "NotImplemented.h" +#include "Page.h" +#include "PlatformKeyboardEvent.h" +#include "SelectionHandler.h" +#include "WebPage_p.h" +#include "WindowsKeyboardCodes.h" + +using namespace BlackBerry::WebKit; + +namespace WebCore { + +// Arbitrary depth limit for the undo stack, to keep it from using +// unbounded memory. This is the maximum number of distinct undoable +// actions -- unbroken stretches of typed characters are coalesced +// into a single action only when not interrupted by string replacements +// triggered by replaceText calls. +static const size_t maximumUndoStackDepth = 1000; + +EditorClientBlackBerry::EditorClientBlackBerry(WebPagePrivate* webPagePrivate) + : m_webPagePrivate(webPagePrivate) + , m_waitingForCursorFocus(false) + , m_spellCheckState(SpellCheckDefault) + , m_inRedo(false) +{ +} + +void EditorClientBlackBerry::pageDestroyed() +{ + delete this; +} + +bool EditorClientBlackBerry::shouldDeleteRange(Range* range) +{ + if (m_webPagePrivate->m_dumpRenderTree) + return m_webPagePrivate->m_dumpRenderTree->shouldDeleteDOMRange(range); + return true; +} + +bool EditorClientBlackBerry::shouldShowDeleteInterface(HTMLElement*) +{ + notImplemented(); + return false; +} + +bool EditorClientBlackBerry::smartInsertDeleteEnabled() +{ + notImplemented(); + return false; +} + +bool EditorClientBlackBerry::isSelectTrailingWhitespaceEnabled() +{ + if (m_webPagePrivate->m_dumpRenderTree) + return m_webPagePrivate->m_dumpRenderTree->isSelectTrailingWhitespaceEnabled(); + return false; +} + +void EditorClientBlackBerry::enableSpellChecking(bool enable) +{ + m_spellCheckState = enable ? SpellCheckDefault : SpellCheckOff; +} + +bool EditorClientBlackBerry::shouldSpellCheckFocusedField() +{ + const Frame* frame = m_webPagePrivate->focusedOrMainFrame(); + if (!frame || !frame->document() || !frame->editor()) + return false; + + const Node* node = frame->document()->focusedNode(); + // NOTE: This logic is taken from EditorClientImpl::shouldSpellcheckByDefault + // If |node| is null, we default to allowing spellchecking. This is done in + // order to mitigate the issue when the user clicks outside the textbox, as a + // result of which |node| becomes null, resulting in all the spell check + // markers being deleted. Also, the Frame will decide not to do spellchecking + // if the user can't edit - so returning true here will not cause any problems + // to the Frame's behavior. + if (!node) + return true; + + // If the field does not support autocomplete, do not do spellchecking. + if (node->isElementNode()) { + const Element* element = static_cast<const Element*>(node); + if (element->hasTagName(HTMLNames::inputTag) && !DOMSupport::elementSupportsAutocomplete(element)) + return false; + } + + // Check if the node disables spell checking directly. + return frame->editor()->isSpellCheckingEnabledInFocusedNode(); +} + +bool EditorClientBlackBerry::isContinuousSpellCheckingEnabled() +{ + if (m_spellCheckState == SpellCheckOff) + return false; + if (m_spellCheckState == SpellCheckOn) + return true; + return shouldSpellCheckFocusedField(); +} + +void EditorClientBlackBerry::toggleContinuousSpellChecking() +{ + // Use the current state to determine how to toggle, if it hasn't + // been explicitly set, it will toggle based on the field type. + if (isContinuousSpellCheckingEnabled()) + m_spellCheckState = SpellCheckOff; + else + m_spellCheckState = SpellCheckOn; +} + +bool EditorClientBlackBerry::isGrammarCheckingEnabled() +{ + notImplemented(); + return false; +} + +void EditorClientBlackBerry::toggleGrammarChecking() +{ + notImplemented(); +} + +int EditorClientBlackBerry::spellCheckerDocumentTag() +{ + notImplemented(); + return 0; +} + +bool EditorClientBlackBerry::shouldBeginEditing(Range* range) +{ + if (m_webPagePrivate->m_dumpRenderTree) + return m_webPagePrivate->m_dumpRenderTree->shouldBeginEditingInDOMRange(range); + + return m_webPagePrivate->m_inputHandler->shouldAcceptInputFocus(); +} + +bool EditorClientBlackBerry::shouldEndEditing(Range* range) +{ + if (m_webPagePrivate->m_dumpRenderTree) + return m_webPagePrivate->m_dumpRenderTree->shouldEndEditingInDOMRange(range); + return true; +} + +bool EditorClientBlackBerry::shouldInsertNode(Node* node, Range* range, EditorInsertAction insertAction) +{ + if (m_webPagePrivate->m_dumpRenderTree) + return m_webPagePrivate->m_dumpRenderTree->shouldInsertNode(node, range, static_cast<int>(insertAction)); + return true; +} + +bool EditorClientBlackBerry::shouldInsertText(const WTF::String& text, Range* range, EditorInsertAction insertAction) +{ + if (m_webPagePrivate->m_dumpRenderTree) + return m_webPagePrivate->m_dumpRenderTree->shouldInsertText(text, range, static_cast<int>(insertAction)); + return true; +} + +bool EditorClientBlackBerry::shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity affinity, bool stillSelecting) +{ + if (m_webPagePrivate->m_dumpRenderTree) + return m_webPagePrivate->m_dumpRenderTree->shouldChangeSelectedDOMRangeToDOMRangeAffinityStillSelecting(fromRange, toRange, static_cast<int>(affinity), stillSelecting); + + Frame* frame = m_webPagePrivate->focusedOrMainFrame(); + if (frame && frame->document()) { + if (frame->document()->focusedNode() && frame->document()->focusedNode()->hasTagName(HTMLNames::selectTag)) + return false; + + // Update the focus state to re-show the keyboard if needed. + // FIXME, this should be removed and strictly be a show keyboard call if + // focus is active. + if (m_webPagePrivate->m_inputHandler->isInputMode()) + m_webPagePrivate->m_inputHandler->nodeFocused(frame->document()->focusedNode()); + } + + return true; +} + +bool EditorClientBlackBerry::shouldApplyStyle(StylePropertySet*, Range*) +{ + notImplemented(); + return true; +} + +bool EditorClientBlackBerry::shouldMoveRangeAfterDelete(Range*, Range*) +{ + notImplemented(); + return true; +} + +void EditorClientBlackBerry::didBeginEditing() +{ + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didBeginEditing(); +} + +void EditorClientBlackBerry::respondToChangedContents() +{ + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didChange(); +} + +void EditorClientBlackBerry::respondToChangedSelection(Frame* frame) +{ + if (m_waitingForCursorFocus) + m_waitingForCursorFocus = false; + else + m_webPagePrivate->selectionChanged(frame); + + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didChangeSelection(); +} + +void EditorClientBlackBerry::didEndEditing() +{ + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didEndEditing(); +} + +void EditorClientBlackBerry::respondToSelectionAppearanceChange() +{ + m_webPagePrivate->m_selectionHandler->selectionPositionChanged(); +} + +void EditorClientBlackBerry::didWriteSelectionToPasteboard() +{ + notImplemented(); +} + +void EditorClientBlackBerry::didSetSelectionTypesForPasteboard() +{ + notImplemented(); +} + +void EditorClientBlackBerry::registerCommandForUndo(PassRefPtr<EditCommand> command) +{ + // Remove the oldest item if we've reached the maximum capacity for the stack. + if (m_undoStack.size() == maximumUndoStackDepth) + m_undoStack.removeFirst(); + + if (!m_inRedo) + m_redoStack.clear(); + + m_undoStack.append(command); +} + +void EditorClientBlackBerry::registerCommandForRedo(PassRefPtr<EditCommand> command) +{ + m_redoStack.append(command); +} + +void EditorClientBlackBerry::clearUndoRedoOperations() +{ + m_undoStack.clear(); + m_redoStack.clear(); +} + +bool EditorClientBlackBerry::canUndo() const +{ + return !m_undoStack.isEmpty(); +} + +bool EditorClientBlackBerry::canRedo() const +{ + return !m_redoStack.isEmpty(); +} + +bool EditorClientBlackBerry::canCopyCut(Frame*, bool defaultValue) const +{ + return defaultValue; +} + +bool EditorClientBlackBerry::canPaste(Frame*, bool defaultValue) const +{ + return defaultValue; +} + +void EditorClientBlackBerry::undo() +{ + if (canUndo()) { + EditCommandStack::iterator back = --m_undoStack.end(); + RefPtr<EditCommand> command(*back); + m_undoStack.remove(back); + + // Unapply will call us back to push this command onto the redo stack. + command->unapply(); + } +} + +void EditorClientBlackBerry::redo() +{ + if (canRedo()) { + EditCommandStack::iterator back = --m_redoStack.end(); + RefPtr<EditCommand> command(*back); + m_redoStack.remove(back); + + ASSERT(!m_inRedo); + m_inRedo = true; + + // Reapply will call us back to push this command onto the undo stack. + command->reapply(); + m_inRedo = false; + } +} + +static const unsigned CtrlKey = 1 << 0; +static const unsigned AltKey = 1 << 1; +static const unsigned ShiftKey = 1 << 2; + +struct KeyDownEntry { + unsigned virtualKey; + unsigned modifiers; + const char* name; +}; + +struct KeyPressEntry { + unsigned charCode; + unsigned modifiers; + const char* name; +}; + +static const KeyDownEntry keyDownEntries[] = { + { VK_LEFT, 0, "MoveLeft" }, + { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" }, + { VK_LEFT, CtrlKey, "MoveWordLeft" }, + { VK_LEFT, CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection" }, + { VK_RIGHT, 0, "MoveRight" }, + { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" }, + { VK_RIGHT, CtrlKey, "MoveWordRight" }, + { VK_RIGHT, CtrlKey | ShiftKey, "MoveWordRightAndModifySelection" }, + { VK_UP, 0, "MoveUp" }, + { VK_UP, ShiftKey, "MoveUpAndModifySelection" }, + { VK_DOWN, 0, "MoveDown" }, + { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" }, + { VK_PRIOR, 0, "MovePageUp" }, + { VK_PRIOR, ShiftKey, "MovePageUpAndModifySelection" }, + { VK_NEXT, 0, "MovePageDown" }, + { VK_NEXT, ShiftKey, "MovePageDownAndModifySelection" }, + { VK_HOME, 0, "MoveToBeginningOfLine" }, + { VK_HOME, ShiftKey, "MoveToBeginningOfLineAndModifySelection" }, + { VK_HOME, CtrlKey, "MoveToBeginningOfDocument" }, + { VK_HOME, CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" }, + { VK_END, 0, "MoveToEndOfLine" }, + { VK_END, ShiftKey, "MoveToEndOfLineAndModifySelection" }, + { VK_END, CtrlKey, "MoveToEndOfDocument" }, + { VK_END, CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection" }, + + { 'B', CtrlKey, "ToggleBold" }, + { 'I', CtrlKey, "ToggleItalic" }, + { 'U', CtrlKey, "ToggleUnderline" }, + + { VK_BACK, 0, "DeleteBackward" }, + { VK_BACK, ShiftKey, "DeleteBackward" }, + { VK_DELETE, 0, "DeleteForward" }, + { VK_BACK, CtrlKey, "DeleteWordBackward" }, + { VK_DELETE, CtrlKey, "DeleteWordForward" }, + + { 'C', CtrlKey, "Copy" }, + { 'V', CtrlKey, "Paste" }, + { 'V', CtrlKey | ShiftKey, "PasteAndMatchStyle" }, + { 'X', CtrlKey, "Cut" }, + { VK_INSERT, CtrlKey, "Copy" }, + { VK_DELETE, ShiftKey, "Cut" }, + { VK_INSERT, ShiftKey, "Paste" }, + + { 'A', CtrlKey, "SelectAll" }, + { 'Z', CtrlKey, "Undo" }, + { 'Z', CtrlKey | ShiftKey, "Redo" }, + { 'Y', CtrlKey, "Redo" }, + + { VK_TAB, 0, "InsertTab" }, + { VK_TAB, ShiftKey, "InsertBacktab" }, + { VK_RETURN, 0, "InsertNewline" }, + { VK_RETURN, CtrlKey, "InsertNewline" }, + { VK_RETURN, AltKey, "InsertNewline" }, + { VK_RETURN, ShiftKey, "InsertLineBreak" }, + { VK_RETURN, AltKey | ShiftKey, "InsertNewline" }, + +}; + +static const KeyPressEntry keyPressEntries[] = { + { '\t', 0, "InsertTab" }, + { '\t', ShiftKey, "InsertBacktab" }, + { '\r', 0, "InsertNewline" }, + { '\r', CtrlKey, "InsertNewline" }, + { '\r', AltKey, "InsertNewline" }, + { '\r', ShiftKey, "InsertLineBreak" }, + { '\r', AltKey | ShiftKey, "InsertNewline" }, +}; + + +const char* EditorClientBlackBerry::interpretKeyEvent(const KeyboardEvent* event) +{ + ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent); + + static HashMap<int, const char*>* keyDownCommandsMap = 0; + static HashMap<int, const char*>* keyPressCommandsMap = 0; + + if (!keyDownCommandsMap) { + keyDownCommandsMap = new HashMap<int, const char*>; + keyPressCommandsMap = new HashMap<int, const char*>; + + for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyDownEntries); ++i) + keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name); + + for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyPressEntries); ++i) + keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); + } + + unsigned modifiers = 0; + if (event->shiftKey()) + modifiers |= ShiftKey; + if (event->altKey()) + modifiers |= AltKey; + if (event->ctrlKey()) + modifiers |= CtrlKey; + + if (event->type() == eventNames().keydownEvent) { + int mapKey = modifiers << 16 | event->keyCode(); + return mapKey ? keyDownCommandsMap->get(mapKey) : 0; + } + + int mapKey = modifiers << 16 | event->charCode(); + return mapKey ? keyPressCommandsMap->get(mapKey) : 0; +} + +void EditorClientBlackBerry::handleKeyboardEvent(KeyboardEvent* event) +{ + ASSERT(event); + + const PlatformKeyboardEvent* platformEvent = event->keyEvent(); + if (!platformEvent) + return; + + ASSERT(event->target()->toNode()); + Frame* frame = event->target()->toNode()->document()->frame(); + ASSERT(frame); + + String commandName = interpretKeyEvent(event); + + if (!commandName.isEmpty()) { + if (frame->editor()->command(commandName).execute()) + event->setDefaultHandled(); + return; + } + + if (!frame->editor()->canEdit()) + return; + + // Text insertion commands should only be triggered from keypressEvent. + // There is an assert guaranteeing this in + // EventHandler::handleTextInputEvent. Note that windowsVirtualKeyCode + // is not set for keypressEvent: special keys should have been already + // handled in keydownEvent, which is called first. + if (event->type() != eventNames().keypressEvent) + return; + + // Don't insert null or control characters as they can result in unexpected behaviour. + if (event->charCode() < ' ') + return; + + // Don't insert anything if a modifier is pressed. + if (event->ctrlKey() || event->altKey()) + return; + + if (!platformEvent->text().isEmpty()) { + if (frame->editor()->insertText(platformEvent->text(), event)) + event->setDefaultHandled(); + } +} + +void EditorClientBlackBerry::handleInputMethodKeydown(KeyboardEvent*) +{ + notImplemented(); +} + +void EditorClientBlackBerry::textFieldDidBeginEditing(Element*) +{ + notImplemented(); +} + +void EditorClientBlackBerry::textFieldDidEndEditing(Element*) +{ + notImplemented(); +} + +void EditorClientBlackBerry::textDidChangeInTextField(Element*) +{ + notImplemented(); +} + +bool EditorClientBlackBerry::doTextFieldCommandFromEvent(Element*, KeyboardEvent*) +{ + notImplemented(); + return false; +} + +void EditorClientBlackBerry::textWillBeDeletedInTextField(Element*) +{ + notImplemented(); +} + +void EditorClientBlackBerry::textDidChangeInTextArea(Element*) +{ + notImplemented(); +} + +void EditorClientBlackBerry::ignoreWordInSpellDocument(const WTF::String&) +{ + notImplemented(); +} + +void EditorClientBlackBerry::learnWord(const WTF::String&) +{ + notImplemented(); +} + +void EditorClientBlackBerry::checkSpellingOfString(const UChar* text, int textLength, int* misspellLocation, int* misspellLength) +{ + m_webPagePrivate->m_client->checkSpellingOfString(text, textLength, *misspellLocation, *misspellLength); +} + +WTF::String EditorClientBlackBerry::getAutoCorrectSuggestionForMisspelledWord(const WTF::String& misspelledWord) +{ + notImplemented(); + return WTF::String(); +} + +void EditorClientBlackBerry::checkGrammarOfString(const UChar*, int, WTF::Vector<GrammarDetail, 0u>&, int*, int*) +{ + notImplemented(); +} + +void EditorClientBlackBerry::requestCheckingOfString(SpellChecker*, const TextCheckingRequest&) +{ + notImplemented(); +} + +TextCheckerClient* EditorClientBlackBerry::textChecker() +{ + return this; +} + +void EditorClientBlackBerry::updateSpellingUIWithGrammarString(const WTF::String&, const GrammarDetail&) +{ + notImplemented(); +} + +void EditorClientBlackBerry::updateSpellingUIWithMisspelledWord(const WTF::String&) +{ + notImplemented(); +} + +void EditorClientBlackBerry::showSpellingUI(bool) +{ + notImplemented(); +} + +bool EditorClientBlackBerry::spellingUIIsShowing() +{ + notImplemented(); + return false; +} + +void EditorClientBlackBerry::getGuessesForWord(const WTF::String&, WTF::Vector<WTF::String, 0u>&) +{ + notImplemented(); +} + +void EditorClientBlackBerry::getGuessesForWord(const String&, const String&, Vector<String>&) +{ + notImplemented(); +} + +void EditorClientBlackBerry::willSetInputMethodState() +{ + notImplemented(); +} + +void EditorClientBlackBerry::setInputMethodState(bool active) +{ + Frame* frame = m_webPagePrivate->focusedOrMainFrame(); + // Determines whether or not to provide input assistance. Password fields + // do not have this flag active, so it needs to be overridden. + if (frame && frame->document()) { + if (Node* focusNode = frame->document()->focusedNode()) { + if (!active && focusNode->hasTagName(HTMLNames::inputTag) + && static_cast<HTMLInputElement*>(focusNode)->isPasswordField()) + active = true; + + if (active) { + m_webPagePrivate->m_inputHandler->nodeFocused(focusNode); + return; + } + } + } + // No frame or document or a node that doesn't support IME. + m_webPagePrivate->m_inputHandler->nodeFocused(0); +} + +} // namespace WebCore diff --git a/Source/WebKit/blackberry/WebCoreSupport/EditorClientBlackBerry.h b/Source/WebKit/blackberry/WebCoreSupport/EditorClientBlackBerry.h new file mode 100644 index 000000000..54a310090 --- /dev/null +++ b/Source/WebKit/blackberry/WebCoreSupport/EditorClientBlackBerry.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef EditorClientBlackBerry_h +#define EditorClientBlackBerry_h + +#include "EditorClient.h" +#include "TextCheckerClient.h" + +#include <wtf/Deque.h> + +namespace BlackBerry { +namespace WebKit { +class WebPagePrivate; +} +} + +namespace WebCore { + +class EditorClientBlackBerry : public EditorClient, public TextCheckerClient { +public: + EditorClientBlackBerry(BlackBerry::WebKit::WebPagePrivate*); + virtual void pageDestroyed(); + virtual bool shouldDeleteRange(Range*); + virtual bool shouldShowDeleteInterface(HTMLElement*); + virtual bool smartInsertDeleteEnabled(); + virtual bool isSelectTrailingWhitespaceEnabled(); + virtual bool isContinuousSpellCheckingEnabled(); + virtual void toggleContinuousSpellChecking(); + virtual bool isGrammarCheckingEnabled(); + virtual void toggleGrammarChecking(); + virtual int spellCheckerDocumentTag(); + virtual bool shouldBeginEditing(Range*); + virtual bool shouldEndEditing(Range*); + virtual bool shouldInsertNode(Node*, Range*, EditorInsertAction); + virtual bool shouldInsertText(const String&, Range*, EditorInsertAction); + virtual bool shouldChangeSelectedRange(Range*, Range*, EAffinity, bool); + virtual bool shouldApplyStyle(StylePropertySet*, Range*); + virtual bool shouldMoveRangeAfterDelete(Range*, Range*); + virtual void didBeginEditing(); + virtual void respondToChangedContents(); + virtual void respondToChangedSelection(Frame*); + virtual void respondToSelectionAppearanceChange(); + virtual void didEndEditing(); + virtual void didWriteSelectionToPasteboard(); + virtual void didSetSelectionTypesForPasteboard(); + virtual void registerCommandForUndo(PassRefPtr<EditCommand>); + virtual void registerCommandForRedo(PassRefPtr<EditCommand>); + virtual void clearUndoRedoOperations(); + virtual bool canCopyCut(Frame*, bool) const; + virtual bool canPaste(Frame*, bool) const; + virtual bool canUndo() const; + virtual bool canRedo() const; + virtual void undo(); + virtual void redo(); + virtual const char* interpretKeyEvent(const KeyboardEvent*); + virtual void handleKeyboardEvent(KeyboardEvent*); + virtual void handleInputMethodKeydown(KeyboardEvent*); + virtual void textFieldDidBeginEditing(Element*); + virtual void textFieldDidEndEditing(Element*); + virtual void textDidChangeInTextField(Element*); + virtual bool doTextFieldCommandFromEvent(Element*, KeyboardEvent*); + virtual void textWillBeDeletedInTextField(Element*); + virtual void textDidChangeInTextArea(Element*); + virtual void ignoreWordInSpellDocument(const String&); + virtual void learnWord(const String&); + virtual void checkSpellingOfString(const UChar*, int, int*, int*); + virtual String getAutoCorrectSuggestionForMisspelledWord(const String& misspelledWord); + virtual void checkGrammarOfString(const UChar*, int, Vector<GrammarDetail, 0u>&, int*, int*); + virtual void getGuessesForWord(const String&, const String&, Vector<String>&); + virtual void requestCheckingOfString(SpellChecker*, const TextCheckingRequest&); + + virtual TextCheckerClient* textChecker(); + virtual void updateSpellingUIWithGrammarString(const String&, const GrammarDetail&); + virtual void updateSpellingUIWithMisspelledWord(const String&); + virtual void showSpellingUI(bool); + virtual bool spellingUIIsShowing(); + virtual void getGuessesForWord(const String&, Vector<String, 0u>&); + virtual void willSetInputMethodState(); + virtual void setInputMethodState(bool); + + void enableSpellChecking(bool); + +private: + bool shouldSpellCheckFocusedField(); + + BlackBerry::WebKit::WebPagePrivate* m_webPagePrivate; + bool m_waitingForCursorFocus; + + enum SpellCheckState { SpellCheckDefault, SpellCheckOn, SpellCheckOff }; + SpellCheckState m_spellCheckState; + + bool m_inRedo; + + typedef Deque<RefPtr<WebCore::EditCommand> > EditCommandStack; + EditCommandStack m_undoStack; + EditCommandStack m_redoStack; +}; + +} // WebCore + +#endif // EditorClientBlackBerry_h diff --git a/Source/WebKit/blackberry/WebCoreSupport/FrameLoaderClientBlackBerry.cpp b/Source/WebKit/blackberry/WebCoreSupport/FrameLoaderClientBlackBerry.cpp new file mode 100644 index 000000000..afddd51a3 --- /dev/null +++ b/Source/WebKit/blackberry/WebCoreSupport/FrameLoaderClientBlackBerry.cpp @@ -0,0 +1,1274 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "FrameLoaderClientBlackBerry.h" + +#include "BackForwardController.h" +#include "BackForwardListImpl.h" +#include "BackingStoreClient.h" +#include "BackingStore_p.h" +#include "Base64.h" +#include "CachedImage.h" +#include "Chrome.h" +#include "ChromeClientBlackBerry.h" +#include "ClientExtension.h" +#include "CookieManager.h" +#include "DumpRenderTreeClient.h" +#include "FrameNetworkingContextBlackBerry.h" +#include "FrameView.h" +#include "HTMLFormElement.h" +#include "HTMLHeadElement.h" +#include "HTMLImageElement.h" +#include "HTMLLinkElement.h" +#include "HTMLMediaElement.h" +#include "HTMLMetaElement.h" +#include "HTMLNames.h" +#include "HTMLPlugInElement.h" +#include "HTTPParsers.h" +#include "HistoryItem.h" +#include "IconDatabase.h" +#include "Image.h" +#include "InputHandler.h" +#include "MIMETypeRegistry.h" +#include "NativeImageSkia.h" +#include "NetworkManager.h" +#include "NodeList.h" +#include "Page.h" +#include "PluginView.h" +#include "ProgressTracker.h" +#include "ScopePointer.h" +#include "SharedBuffer.h" +#include "TextEncoding.h" +#include "TouchEventHandler.h" +#if ENABLE(WEBDOM) +#include "WebDOMDocument.h" +#endif +#include "WebPageClient.h" + +#include <BlackBerryPlatformLog.h> +#include <BlackBerryPlatformScreen.h> +#include <JavaScriptCore/APICast.h> +#include <network/FilterStream.h> +#include <network/NetworkRequest.h> + +using WTF::String; +using namespace WebCore; +using namespace BlackBerry::WebKit; + +// This was copied from file "WebKit/Source/WebKit/mac/Misc/WebKitErrors.h". +enum { + WebKitErrorCannotShowMIMEType = 100, + WebKitErrorCannotShowURL = 101, + WebKitErrorFrameLoadInterruptedByPolicyChange = 102, + WebKitErrorCannotUseRestrictedPort = 103, + WebKitErrorCannotFindPlugIn = 200, + WebKitErrorCannotLoadPlugIn = 201, + WebKitErrorJavaUnavailable = 202, + WebKitErrorPluginWillHandleLoad = 203 +}; + +namespace WebCore { + +FrameLoaderClientBlackBerry::FrameLoaderClientBlackBerry() + : m_frame(0) + , m_webPagePrivate(0) + , m_sentReadyToRender(false) + , m_pendingFragmentScrollPolicyFunction(0) + , m_loadingErrorPage(false) + , m_clientRedirectIsPending(false) + , m_childFrameCreationSuppressed(false) + , m_pluginView(0) + , m_hasSentResponseToPlugin(false) + , m_cancelLoadOnNextData(false) +{ + m_deferredJobsTimer = new Timer<FrameLoaderClientBlackBerry>(this, &FrameLoaderClientBlackBerry::deferredJobsTimerFired); +} + +FrameLoaderClientBlackBerry::~FrameLoaderClientBlackBerry() +{ + delete m_deferredJobsTimer; + m_deferredJobsTimer = 0; +} + +int FrameLoaderClientBlackBerry::playerId() const +{ + if (m_webPagePrivate && m_webPagePrivate->m_client) + return m_webPagePrivate->m_client->getInstanceId(); + return 0; +} + +bool FrameLoaderClientBlackBerry::cookiesEnabled() const +{ + return m_webPagePrivate->m_webSettings->areCookiesEnabled(); +} + +void FrameLoaderClientBlackBerry::dispatchDidAddBackForwardItem(HistoryItem* item) const +{ + // Inform the client that the back/forward list has changed. + invalidateBackForwardList(); +} + +void FrameLoaderClientBlackBerry::dispatchDidRemoveBackForwardItem(HistoryItem* item) const +{ + invalidateBackForwardList(); +} + +void FrameLoaderClientBlackBerry::dispatchDidChangeBackForwardIndex() const +{ + invalidateBackForwardList(); +} + +void FrameLoaderClientBlackBerry::dispatchDidChangeLocationWithinPage() +{ + if (!isMainFrame()) + return; + + String url = m_frame->document()->url().string(); + String token = m_frame->loader()->documentLoader()->request().token(); + + m_webPagePrivate->m_client->notifyLoadToAnchor(url.characters(), url.length(), token.characters(), token.length()); +} + +void FrameLoaderClientBlackBerry::dispatchDidPushStateWithinPage() +{ + // FIXME: As a workaround we abuse anchor navigation to achieve history push. See PR #119779 for more details. + dispatchDidChangeLocationWithinPage(); +} + +void FrameLoaderClientBlackBerry::dispatchDidReplaceStateWithinPage() +{ + // FIXME: As a workaround we abuse anchor navigation to achieve history replace. See PR #119779 for more details. + dispatchDidChangeLocationWithinPage(); +} + +void FrameLoaderClientBlackBerry::dispatchDidPopStateWithinPage() +{ + // Not needed. +} + +void FrameLoaderClientBlackBerry::dispatchDidCancelClientRedirect() +{ + m_clientRedirectIsPending = false; +} + +void FrameLoaderClientBlackBerry::dispatchWillPerformClientRedirect(const KURL&, double, double) +{ + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didDispatchWillPerformClientRedirect(); + + m_clientRedirectIsPending = true; +} + +void FrameLoaderClientBlackBerry::dispatchDecidePolicyForResponse(FramePolicyFunction function, const ResourceResponse& response, const ResourceRequest& request) +{ + // FIXME: What should we do for HTTP status code 204 and 205 and "application/zip"? + PolicyAction policy = PolicyIgnore; + + if (contentDispositionType(response.httpHeaderField("Content-Disposition")) == ContentDispositionAttachment + || request.forceDownload()) + policy = PolicyDownload; + else if (canShowMIMEType(response.mimeType())) + policy = PolicyUse; + else if ((ResourceRequest::TargetIsMainFrame == request.targetType()) + && m_webPagePrivate->m_client->downloadAllowed(request.url().string().utf8().data())) + policy = PolicyDownload; + + (m_frame->loader()->policyChecker()->*function)(policy); +} + +void FrameLoaderClientBlackBerry::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState>) +{ + PolicyAction decision = PolicyUse; + + const KURL& url = request.url(); + + // Fragment scrolls on the same page should always be handled internally. + // (Only count as a fragment scroll if we are scrolling to a #fragment url, not back to the top, and reloading + // the same url is not a fragment scroll even if it has a #fragment.) + const KURL& currentUrl = m_frame->document()->url(); + bool isFragmentScroll = url.hasFragmentIdentifier() && url != currentUrl && equalIgnoringFragmentIdentifier(currentUrl, url); + if (decision == PolicyUse) + decision = decidePolicyForExternalLoad(request, isFragmentScroll); + + // Let the client have a chance to say whether this navigation should + // be ignored or not. + BlackBerry::Platform::NetworkRequest platformRequest; + request.initializePlatformRequest(platformRequest, false /*isInitial*/); + if (isMainFrame() && !m_webPagePrivate->m_client->acceptNavigationRequest( + platformRequest, BlackBerry::Platform::NavigationType(action.type()))) { + if (action.type() == NavigationTypeFormSubmitted + || action.type() == NavigationTypeFormResubmitted) + m_frame->loader()->resetMultipleFormSubmissionProtection(); + + if (action.type() == NavigationTypeLinkClicked && url.hasFragmentIdentifier()) { + ResourceRequest emptyRequest; + m_frame->loader()->activeDocumentLoader()->setLastCheckedRequest(emptyRequest); + } + decision = PolicyIgnore; + } + + // If we abort here, dispatchDidCancelClientRedirect will not be called. + // So call it by hand. + if (decision == PolicyIgnore) + dispatchDidCancelClientRedirect(); + + (m_frame->loader()->policyChecker()->*function)(decision); + + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didDecidePolicyForNavigationAction(action, request); +} + +void FrameLoaderClientBlackBerry::delayPolicyCheckUntilFragmentExists(const String& fragment, FramePolicyFunction function) +{ + ASSERT(isMainFrame()); + + if (m_webPagePrivate->loadState() < WebPagePrivate::Finished && !m_frame->document()->findAnchor(fragment)) { + // Tell the client we need more data, in case the fragment exists but is being held back. + m_webPagePrivate->m_client->needMoreData(); + m_pendingFragmentScrollPolicyFunction = function; + m_pendingFragmentScroll = fragment; + return; + } + + (m_frame->loader()->policyChecker()->*function)(PolicyUse); +} + +void FrameLoaderClientBlackBerry::cancelPolicyCheck() +{ + m_pendingFragmentScrollPolicyFunction = 0; + m_pendingFragmentScroll = String(); +} + +void FrameLoaderClientBlackBerry::doPendingFragmentScroll() +{ + if (m_pendingFragmentScroll.isNull()) + return; + + // Make sure to clear the pending members first to avoid recursion. + String fragment = m_pendingFragmentScroll; + m_pendingFragmentScroll = String(); + + FramePolicyFunction function = m_pendingFragmentScrollPolicyFunction; + m_pendingFragmentScrollPolicyFunction = 0; + + delayPolicyCheckUntilFragmentExists(fragment, function); +} + +void FrameLoaderClientBlackBerry::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState>, const String& frameName) +{ + if (request.isRequestedByPlugin() && ScriptController::processingUserGesture() && !m_webPagePrivate->m_pluginMayOpenNewTab) + (m_frame->loader()->policyChecker()->*function)(PolicyIgnore); + + // A new window can never be a fragment scroll. + PolicyAction decision = decidePolicyForExternalLoad(request, false); + // Let the client have a chance to say whether this navigation should + // be ignored or not. + BlackBerry::Platform::NetworkRequest platformRequest; + request.initializePlatformRequest(platformRequest, false /*isInitial*/); + if (isMainFrame() && !m_webPagePrivate->m_client->acceptNavigationRequest( + platformRequest, BlackBerry::Platform::NavigationType(action.type()))) { + if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted) + m_frame->loader()->resetMultipleFormSubmissionProtection(); + + if (action.type() == NavigationTypeLinkClicked && request.url().hasFragmentIdentifier()) { + ResourceRequest emptyRequest; + m_frame->loader()->activeDocumentLoader()->setLastCheckedRequest(emptyRequest); + } + decision = PolicyIgnore; + } + + (m_frame->loader()->policyChecker()->*function)(decision); +} + +void FrameLoaderClientBlackBerry::committedLoad(DocumentLoader* loader, const char* data, int length) +{ + // The structure of this code may seem...a bit odd. It's structured with two checks on the state + // of m_pluginView because it's actually receivedData that may cause the request to re-direct data + // to a PluginView. This is because receivedData may decide to create a PluginDocument containing + // a PluginView. The PluginView will request that the main resource for the frame be redirected + // to the PluginView. So after receivedData has been called, this code needs to check whether + // re-direction to a PluginView has been requested and pass the same data on to the PluginView. + // Thereafter, all data will be re-directed to the PluginView; i.e., no additional data will go + // to receivedData. + + if (!m_pluginView) { + const String& textEncoding = loader->response().textEncodingName(); + receivedData(data, length, textEncoding); + } + + if (m_pluginView) { + if (!m_hasSentResponseToPlugin) { + m_pluginView->didReceiveResponse(loader->response()); + m_hasSentResponseToPlugin = true; + } + + if (!m_pluginView) + return; + + m_pluginView->didReceiveData(data, length); + } +} + +PassRefPtr<Widget> FrameLoaderClientBlackBerry::createPlugin(const IntSize& pluginSize, + HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames, + const Vector<String>& paramValues, const String& mimeTypeIn, bool loadManually) +{ + String mimeType(mimeTypeIn); + if (mimeType.isEmpty()) { + mimeType = MIMETypeRegistry::getMIMETypeForPath(url.path()); + mimeType = WebSettings::getNormalizedMIMEType(mimeType); + if (mimeType != "application/x-shockwave-flash") + mimeType = mimeTypeIn; + } + + if (mimeType == "application/x-shockwave-flash" || mimeType == "application/jnext-scriptable-plugin") + return PluginView::create(m_frame, pluginSize, element, url, paramNames, paramValues, mimeType, loadManually); + + // If it's not the plugin type we support, try load directly from browser. + if (m_frame->loader() && m_frame->loader()->subframeLoader() && !url.isNull()) + m_frame->loader()->subframeLoader()->requestFrame(element, url, String()); + + return 0; +} + +void FrameLoaderClientBlackBerry::redirectDataToPlugin(Widget* pluginWidget) +{ + ASSERT(!m_pluginView); + m_pluginView = static_cast<PluginView*>(pluginWidget); + m_hasSentResponseToPlugin = false; +} + +void FrameLoaderClientBlackBerry::receivedData(const char* data, int length, const String& textEncoding) +{ + if (!m_frame) + return; + + if (m_cancelLoadOnNextData) { + m_frame->loader()->activeDocumentLoader()->stopLoading(); + m_frame->loader()->documentLoader()->writer()->end(); + m_cancelLoadOnNextData = false; + return; + } + + // Set the encoding. This only needs to be done once, but it's harmless to do it again later. + String encoding = m_frame->loader()->documentLoader()->overrideEncoding(); + bool userChosen = !encoding.isNull(); + if (encoding.isNull()) + encoding = textEncoding; + m_frame->loader()->documentLoader()->writer()->setEncoding(encoding, userChosen); + m_frame->loader()->documentLoader()->writer()->addData(data, length); +} + +void FrameLoaderClientBlackBerry::finishedLoading(DocumentLoader* loader) +{ + if (m_pluginView) { + m_pluginView->didFinishLoading(); + m_pluginView = 0; + m_hasSentResponseToPlugin = false; + } else { + // Telling the frame we received some data and passing 0 as the data is our + // way to get work done that is normally done when the first bit of data is + // received, even for the case of a document with no data (like about:blank). + committedLoad(loader, 0, 0); + } +} + +PassRefPtr<DocumentLoader> FrameLoaderClientBlackBerry::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData) +{ + // Make a copy of the request with the token from the original request for this frame + // (unless it already has a token, in which case the request came from the client). + ResourceRequest newRequest(request); + if (m_frame && m_frame->loader() && m_frame->loader()->documentLoader()) { + const ResourceRequest& originalRequest = m_frame->loader()->documentLoader()->originalRequest(); + if (request.token().isNull() && !originalRequest.token().isNull()) + newRequest.setToken(originalRequest.token()); + } + + // FIXME: This should probably be shared. + RefPtr<DocumentLoader> loader = DocumentLoader::create(newRequest, substituteData); + if (substituteData.isValid()) + loader->setDeferMainResourceDataLoad(false); + return loader.release(); +} + +void FrameLoaderClientBlackBerry::frameLoaderDestroyed() +{ + delete this; +} + +void FrameLoaderClientBlackBerry::transitionToCommittedForNewPage() +{ + m_cancelLoadOnNextData = false; + + // In Frame::createView, Frame's FrameView object is set to 0 and recreated. + // This operation is not atomic, and an attempt to blit contents might happen + // in the backing store from another thread (see BackingStorePrivate::blitContents method), + // so we suspend and resume screen update to make sure we do not get a invalid FrameView + // state. + BackingStoreClient* backingStoreClientForFrame = m_webPagePrivate->backingStoreClientForFrame(m_frame); + if (backingStoreClientForFrame) + backingStoreClientForFrame->backingStore()->d->suspendScreenAndBackingStoreUpdates(); + + // We are navigating away from this document, so clean up any footprint we might have. + if (m_frame->document()) + m_webPagePrivate->clearDocumentData(m_frame->document()); + + Color backgroundColor(m_webPagePrivate->m_webSettings->backgroundColor()); + + m_frame->createView(m_webPagePrivate->viewportSize(), /* viewport */ + backgroundColor, /* background color */ + backgroundColor.hasAlpha(), /* is transparent */ + m_webPagePrivate->actualVisibleSize(), /* fixed reported size */ + m_webPagePrivate->fixedLayoutSize(), /* fixed layout size */ + m_webPagePrivate->useFixedLayout(), /* use fixed layout */ + ScrollbarAlwaysOff, /* hor mode */ + true, /* lock the mode */ + ScrollbarAlwaysOff, /* ver mode */ + true); /* lock the mode */ + + if (backingStoreClientForFrame) + backingStoreClientForFrame->backingStore()->d->resumeScreenAndBackingStoreUpdates(BackingStore::None); + m_frame->view()->updateCanHaveScrollbars(); + + if (isMainFrame()) { + // Since the mainframe has a tiled backingstore request to receive all update + // rects instead of the default which just sends update rects for currently + // visible viewport. + m_frame->view()->setPaintsEntireContents(true); + } +} + +String FrameLoaderClientBlackBerry::userAgent(const KURL&) +{ + return m_webPagePrivate->m_webSettings->userAgentString(); +} + +bool FrameLoaderClientBlackBerry::canHandleRequest(const ResourceRequest&) const +{ + // FIXME: Stub. + return true; +} + +bool FrameLoaderClientBlackBerry::canShowMIMEType(const String& mimeTypeIn) const +{ + // Get normalized type. + String mimeType = WebSettings::getNormalizedMIMEType(mimeTypeIn); + + // FIXME: Seems no other port checks empty MIME type in this function. Should we do that? + return MIMETypeRegistry::isSupportedImageMIMEType(mimeType) || MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType) + || MIMETypeRegistry::isSupportedMediaMIMEType(mimeType) || WebSettings::isSupportedObjectMIMEType(mimeType) + || (mimeType == "application/x-shockwave-flash"); +} + +bool FrameLoaderClientBlackBerry::canShowMIMETypeAsHTML(const String&) const +{ + // FIXME: Stub. + return true; +} + +bool FrameLoaderClientBlackBerry::isMainFrame() const +{ + return m_frame == m_webPagePrivate->m_mainFrame; +} + +void FrameLoaderClientBlackBerry::dispatchDidStartProvisionalLoad() +{ + if (isMainFrame()) + m_webPagePrivate->setLoadState(WebPagePrivate::Provisional); + + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didStartProvisionalLoadForFrame(m_frame); +} + +void FrameLoaderClientBlackBerry::dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse& response) +{ + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didReceiveResponseForFrame(m_frame, response); +} + +void FrameLoaderClientBlackBerry::dispatchDidReceiveTitle(const StringWithDirection& title) +{ + if (isMainFrame()) + m_webPagePrivate->m_client->setPageTitle(title.string().characters(), title.string().length()); + + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didReceiveTitleForFrame(title.string(), m_frame); +} + +void FrameLoaderClientBlackBerry::setTitle(const StringWithDirection& /*title*/, const KURL& /*url*/) +{ + // Used by Apple WebKit to update the title of an existing history item. + // QtWebKit doesn't accomodate this on history items. If it ever does, + // it should be privateBrowsing-aware. For now, we are just passing + // globalhistory layout tests. + // FIXME: Use direction of title. + notImplemented(); +} + +void FrameLoaderClientBlackBerry::dispatchDidCommitLoad() +{ + // FIXME: Do we need to find a replacement for m_frame->document()->setExtraLayoutDelay(250);? + + if (isMainFrame()) { + m_webPagePrivate->setLoadState(WebPagePrivate::Committed); + + String originalUrl = m_frame->loader()->documentLoader()->originalRequest().url().string(); + String url = m_frame->loader()->documentLoader()->request().url().string(); + String token = m_frame->loader()->documentLoader()->request().token(); + + // Notify the client that the load succeeded or failed (if it failed, this + // is actually committing the error page, which was set through + // SubstituteData in dispatchDidFailProvisionalLoad). + if (m_loadingErrorPage) { + m_loadingErrorPage = false; + m_webPagePrivate->m_client->notifyLoadFailedBeforeCommit( + originalUrl.characters(), originalUrl.length(), + url.characters(), url.length(), token.characters(), token.length()); + } else { + m_webPagePrivate->m_client->notifyLoadCommitted( + originalUrl.characters(), originalUrl.length(), + url.characters(), url.length(), token.characters(), token.length()); + } + } + + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didCommitLoadForFrame(m_frame); +} + +void FrameLoaderClientBlackBerry::dispatchDidHandleOnloadEvents() +{ + m_webPagePrivate->m_client->notifyDocumentOnLoad(); + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didHandleOnloadEventsForFrame(m_frame); +} + +void FrameLoaderClientBlackBerry::dispatchDidFinishLoad() +{ + didFinishOrFailLoading(ResourceError()); + + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didFinishLoadForFrame(m_frame); + + if (!isMainFrame() || m_webPagePrivate->m_webSettings->isEmailMode() + || !m_frame->document() || !m_frame->document()->head()) + return; + + HTMLHeadElement* headElement = m_frame->document()->head(); + // FIXME: Handle NOSCRIPT special case? + + // Process document metadata. + RefPtr<NodeList> nodeList = headElement->getElementsByTagName(HTMLNames::metaTag.localName()); + unsigned int size = nodeList->length(); + ScopeArray<WebString> headers; + + // This may allocate more space than needed since not all meta elements will be http-equiv. + headers.reset(new WebString[2 * size]); + unsigned headersLength = 0; + + for (unsigned i = 0; i < size; ++i) { + HTMLMetaElement* metaElement = static_cast<HTMLMetaElement*>(nodeList->item(i)); + if (WTF::equalIgnoringCase(metaElement->name(), "apple-mobile-web-app-capable") + && WTF::equalIgnoringCase(metaElement->content().stripWhiteSpace(), "yes")) + m_webPagePrivate->m_client->setWebAppCapable(); + else { + String httpEquiv = metaElement->httpEquiv().stripWhiteSpace(); + String content = metaElement->content().stripWhiteSpace(); + + if (!httpEquiv.isNull() && !content.isNull()) { + headers[headersLength++] = httpEquiv; + headers[headersLength++] = content; + } + } + } + + if (headersLength > 0) + m_webPagePrivate->m_client->setMetaHeaders(headers, headersLength); + + nodeList = headElement->getElementsByTagName(HTMLNames::linkTag.localName()); + size = nodeList->length(); + + for (unsigned i = 0; i < size; ++i) { + HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(nodeList->item(i)); + String href = linkElement->href().string(); + if (!href.isEmpty()) { + String title = linkElement->title(); + + if (WTF::equalIgnoringCase(linkElement->rel(), "apple-touch-icon")) + m_webPagePrivate->m_client->setLargeIcon(href.latin1().data()); + else if (WTF::equalIgnoringCase(linkElement->rel(), "search")) { + if (WTF::equalIgnoringCase(linkElement->type(), "application/opensearchdescription+xml")) + m_webPagePrivate->m_client->setSearchProviderDetails(title.utf8().data(), href.utf8().data()); + } else if (WTF::equalIgnoringCase(linkElement->rel(), "alternate") + && (WTF::equalIgnoringCase(linkElement->type(), "application/rss+xml") + || WTF::equalIgnoringCase(linkElement->type(), "application/atom+xml"))) + m_webPagePrivate->m_client->setAlternateFeedDetails(title.utf8().data(), href.utf8().data()); + } + } +} + +void FrameLoaderClientBlackBerry::dispatchDidFinishDocumentLoad() +{ + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didFinishDocumentLoadForFrame(m_frame); + notImplemented(); +} + +void FrameLoaderClientBlackBerry::dispatchDidFailLoad(const ResourceError& error) +{ + didFinishOrFailLoading(error); + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didFailLoadForFrame(m_frame); +} + +void FrameLoaderClientBlackBerry::didFinishOrFailLoading(const ResourceError& error) +{ + // FIXME: Do we need to find a replacement for m_frame->document()->setExtraLayoutDelay(0);? + + // If we have finished loading a page through history navigation, any + // attempt to go back to that page through an automatic redirect should be + // denied to avoid redirect loops. So save the history navigation urls to + // check later. (If this was not a history navigation, + // m_historyNavigationSourceURLs will be empty, and we should save that + // too.) + m_redirectURLsToSkipDueToHistoryNavigation.swap(m_historyNavigationSourceURLs); + + // History navigation is finished so clear the history navigation url. + m_historyNavigationSourceURLs.clear(); + + if (isMainFrame()) { + m_loadError = error; + m_webPagePrivate->setLoadState(error.isNull() ? WebPagePrivate::Finished : WebPagePrivate::Failed); + } +} + +void FrameLoaderClientBlackBerry::dispatchDidFailProvisionalLoad(const ResourceError& error) +{ + if (isMainFrame()) { + m_loadError = error; + m_webPagePrivate->setLoadState(WebPagePrivate::Failed); + + if (error.domain() == ResourceError::platformErrorDomain + && (error.errorCode() == BlackBerry::Platform::FilterStream::StatusErrorAlreadyHandled)) { + // Error has already been displayed by client. + return; + } + + if (error.domain().isEmpty() && !error.errorCode() && error.failingURL().isEmpty() && error.localizedDescription().isEmpty()) { + // Don't try to display empty errors returned from the unimplemented error functions in FrameLoaderClientBlackBerry - there's nothing to display anyway. + return; + } + } + + if (m_webPagePrivate->m_dumpRenderTree) + m_webPagePrivate->m_dumpRenderTree->didFailProvisionalLoadForFrame(m_frame); + + if (!isMainFrame()) + return; + + String errorPage = m_webPagePrivate->m_client->getErrorPage(error.errorCode() + , error.localizedDescription().isEmpty() ? "" : error.localizedDescription().utf8().data() + , error.failingURL().isEmpty() ? "" : error.failingURL().utf8().data()); + + // Make sure we're still in the provisionalLoad state - getErrorPage runs a + // nested event loop while it's waiting for client resources to load so + // there's a small window for the user to hit stop. + if (m_frame->loader()->provisionalDocumentLoader()) { + SubstituteData errorData(utf8Buffer(errorPage), "text/html", "utf-8", KURL(KURL(), error.failingURL())); + + ResourceRequest originalRequest = m_frame->loader()->provisionalDocumentLoader()->originalRequest(); + + // Loading using SubstituteData will replace the original request with our + // error data. This must be done within dispatchDidFailProvisionalLoad, + // and do NOT call stopAllLoaders first, because the loader checks the + // provisionalDocumentLoader to decide the load type; if called any other + // way, the error page is added to the end of the history instead of + // replacing the failed load. + // + // If this comes from a back/forward navigation, we need to save the current viewstate + // to original historyitem, and prevent the restore of view state to the error page. + if (isBackForwardLoadType(m_frame->loader()->loadType())) { + m_frame->loader()->history()->saveScrollPositionAndViewStateToItem(m_frame->loader()->history()->currentItem()); + ASSERT(m_frame->loader()->history()->provisionalItem()); + m_frame->loader()->history()->provisionalItem()->viewState().shouldSaveViewState = false; + } + m_loadingErrorPage = true; + m_frame->loader()->load(originalRequest, errorData, false); + } +} + +void FrameLoaderClientBlackBerry::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState>) +{ + // FIXME: Stub. + (m_frame->loader()->policyChecker()->*function)(PolicyUse); +} + +PassRefPtr<Frame> FrameLoaderClientBlackBerry::createFrame(const KURL& url, const String& name + , HTMLFrameOwnerElement* ownerElement, const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) +{ + if (!m_webPagePrivate) + return 0; + + if (m_childFrameCreationSuppressed) + return 0; + + FrameLoaderClientBlackBerry* frameLoaderClient = new FrameLoaderClientBlackBerry(); + RefPtr<Frame> childFrame = Frame::create(m_frame->page(), ownerElement, frameLoaderClient); + frameLoaderClient->setFrame(childFrame.get(), m_webPagePrivate); + + // Initialize FrameView. + RefPtr<FrameView> frameView = FrameView::create(childFrame.get()); + childFrame->setView(frameView.get()); + if (!allowsScrolling) + frameView->setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); + if (marginWidth != -1) + frameView->setMarginWidth(marginWidth); + if (marginHeight != -1) + frameView->setMarginHeight(marginHeight); + + childFrame->tree()->setName(name); + m_frame->tree()->appendChild(childFrame); + childFrame->init(); + + if (!childFrame->tree()->parent()) + return 0; + + BackingStoreClient::create(childFrame.get(), m_frame, m_webPagePrivate->m_webPage); + + m_frame->loader()->loadURLIntoChildFrame(url, referrer, childFrame.get()); + + if (!childFrame->tree()->parent()) + return 0; + + return childFrame.release(); +} + +void FrameLoaderClientBlackBerry::didTransferChildFrameToNewDocument(Page* /*oldPage*/) +{ + Page* newPage = m_frame->page(); + m_webPagePrivate = static_cast<ChromeClientBlackBerry*>(newPage->chrome()->client())->webPagePrivate(); +} + +void FrameLoaderClientBlackBerry::transferLoadingResourceFromPage(ResourceLoader*, const ResourceRequest&, Page*) +{ + notImplemented(); +} + +ObjectContentType FrameLoaderClientBlackBerry::objectContentType(const KURL& url, const String& mimeTypeIn, bool shouldPreferPlugInsForImages) +{ + String mimeType = mimeTypeIn; + if (mimeType.isEmpty()) + mimeType = MIMETypeRegistry::getMIMETypeForPath(url.path()); + + // Get mapped type. + mimeType = WebSettings::getNormalizedMIMEType(mimeType); + + ObjectContentType defaultType = FrameLoader::defaultObjectContentType(url, mimeType, shouldPreferPlugInsForImages); + if (defaultType != ObjectContentNone) + return defaultType; + + if (WebSettings::isSupportedObjectMIMEType(mimeType)) + return ObjectContentOtherPlugin; + + return ObjectContentNone; +} + +void FrameLoaderClientBlackBerry::dispatchWillClose() +{ + m_webPagePrivate->m_inputHandler->frameUnloaded(m_frame); +} + +void FrameLoaderClientBlackBerry::setMainDocumentError(DocumentLoader*, const ResourceError& error) +{ + if (!m_pluginView) + return; + + m_pluginView->didFail(error); + m_pluginView = 0; + m_hasSentResponseToPlugin = false; +} + +void FrameLoaderClientBlackBerry::postProgressStartedNotification() +{ + if (!isMainFrame()) + return; + + // New load started, so clear the error. + m_loadError = ResourceError(); + m_sentReadyToRender = false; + m_webPagePrivate->m_client->notifyLoadStarted(); +} + +void FrameLoaderClientBlackBerry::postProgressEstimateChangedNotification() +{ + if (!isMainFrame() || !m_frame->page()) + return; + + m_webPagePrivate->m_client->notifyLoadProgress(m_frame->page()->progress()->estimatedProgress() * 100); +} + +void FrameLoaderClientBlackBerry::dispatchDidFirstVisuallyNonEmptyLayout() +{ + if (!isMainFrame()) + return; + + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "dispatchDidFirstVisuallyNonEmptyLayout"); + + readyToRender(true); + + // FIXME: We shouldn't be getting here if we are not in the Committed state but we are + // so we can not assert on that right now. But we only want to do this on load. + // RIM Bug #555 + if (m_webPagePrivate->loadState() == WebPagePrivate::Committed) { + m_webPagePrivate->zoomToInitialScaleOnLoad(); // Set the proper zoom level first. + m_webPagePrivate->m_backingStore->d->clearVisibleZoom(); // Clear the visible zoom since we're explicitly rendering+blitting below. + m_webPagePrivate->m_backingStore->d->renderVisibleContents(); + } + + m_webPagePrivate->m_client->notifyFirstVisuallyNonEmptyLayout(); +} + +void FrameLoaderClientBlackBerry::postProgressFinishedNotification() +{ + if (!isMainFrame()) + return; + + // Empty pages will never have called + // dispatchDidFirstVisuallyNonEmptyLayout, since they're visually empty, so + // we may need to call readyToRender now. + readyToRender(false); + + // FIXME: Send up a real status code. + m_webPagePrivate->m_client->notifyLoadFinished(m_loadError.isNull() ? 0 : -1); + + // Notify plugins that are waiting for the page to fully load before starting that + // the load has completed. + m_webPagePrivate->notifyPageOnLoad(); +} + +void FrameLoaderClientBlackBerry::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world) +{ + if (world != mainThreadNormalWorld()) + return; + + // Provide the extension object first in case the client or others want to use it. + // FIXME: Conditionally attach extension object based on some flag or whether or not we + // are browser or something else. + attachExtensionObjectToFrame(m_frame, m_webPagePrivate->m_client); + + m_webPagePrivate->m_client->notifyWindowObjectCleared(); + + if (m_webPagePrivate->m_dumpRenderTree) { + JSGlobalContextRef context = toGlobalRef(m_frame->script()->globalObject(mainThreadNormalWorld())->globalExec()); + JSObjectRef windowObject = toRef(m_frame->script()->globalObject(mainThreadNormalWorld())); + ASSERT(windowObject); + m_webPagePrivate->m_dumpRenderTree->didClearWindowObjectInWorld(world, context, windowObject); + } +} + +bool FrameLoaderClientBlackBerry::shouldGoToHistoryItem(HistoryItem*) const +{ + return true; +} + +bool FrameLoaderClientBlackBerry::shouldStopLoadingForHistoryItem(HistoryItem*) const +{ + return true; +} + +void FrameLoaderClientBlackBerry::invalidateBackForwardList() const +{ + notifyBackForwardListChanged(); +} + +void FrameLoaderClientBlackBerry::notifyBackForwardListChanged() const +{ + BackForwardListImpl* backForwardList = static_cast<BackForwardListImpl*>(m_webPagePrivate->m_page->backForward()->client()); + ASSERT(backForwardList); + + unsigned listSize = backForwardList->entries().size(); + unsigned currentIndex = backForwardList->backListCount(); + m_webPagePrivate->m_client->resetBackForwardList(listSize, currentIndex); +} + +Frame* FrameLoaderClientBlackBerry::dispatchCreatePage(const NavigationAction& navigation) +{ + WebPage* webPage = m_webPagePrivate->m_client->createWindow(0, 0, -1, -1, WebPageClient::FlagWindowDefault, navigation.url().string(), WebString()); + if (!webPage) + return 0; + + return webPage->d->m_page->mainFrame(); +} + +void FrameLoaderClientBlackBerry::detachedFromParent2() +{ + BackingStoreClient* backingStoreClientForFrame = m_webPagePrivate->backingStoreClientForFrame(m_frame); + if (backingStoreClientForFrame) { + delete backingStoreClientForFrame; + backingStoreClientForFrame = 0; + } + + if (m_frame->document()) + m_webPagePrivate->clearDocumentData(m_frame->document()); + + m_webPagePrivate->m_inputHandler->frameUnloaded(m_frame); + m_webPagePrivate->m_client->notifyFrameDetached(m_frame); +} + +void FrameLoaderClientBlackBerry::dispatchWillSendRequest(DocumentLoader* docLoader, long unsigned int, ResourceRequest& request, const ResourceResponse&) +{ + // If the request is being loaded by the provisional document loader, then + // it is a new top level request which has not been commited. + bool isMainResourceLoad = docLoader && docLoader == docLoader->frameLoader()->provisionalDocumentLoader(); + + // Any processing which is done for all loads (both main and subresource) should go here. + BlackBerry::Platform::NetworkRequest platformRequest; + request.initializePlatformRequest(platformRequest, false /*isInitial*/); + m_webPagePrivate->m_client->populateCustomHeaders(platformRequest); + const BlackBerry::Platform::NetworkRequest::HeaderList& headerLists = platformRequest.getHeaderListRef(); + for (BlackBerry::Platform::NetworkRequest::HeaderList::const_iterator it = headerLists.begin(); it != headerLists.end(); ++it) { + std::string headerString = it->first; + std::string headerValueString = it->second; + request.setHTTPHeaderField(String(headerString.c_str()), String(headerValueString.c_str())); + } + if (cookiesEnabled()) { + String cookiePairs = cookieManager().getCookie(request.url(), WithHttpOnlyCookies); + if (!cookiePairs.isEmpty()) { + // We only modify the WebCore request to make the cookies visible in inspector. + request.setHTTPHeaderField(String("Cookie"), cookiePairs); + } + } + if (!isMainResourceLoad) { + // Do nothing for now. + // Any processing which is done only for subresources should go here. + return; + } + + // All processing beyond this point is done only for main resource loads. + + if (m_clientRedirectIsPending && isMainFrame()) { + String originalUrl = m_frame->document()->url().string(); + String finalUrl = request.url().string(); + + m_webPagePrivate->m_client->notifyClientRedirect(originalUrl.characters(), originalUrl.length(), + finalUrl.characters(), finalUrl.length()); + } + + // FIXME: Update the request type. See PR #119792. + if (docLoader->frameLoader()->isLoadingMainFrame()) + request.setTargetType(ResourceRequest::TargetIsMainFrame); + else + request.setTargetType(ResourceRequest::TargetIsSubframe); + + FrameLoader* loader = m_frame->loader(); + ASSERT(loader); + if (isBackForwardLoadType(loader->loadType())) { + // Do not use the passed DocumentLoader because it is the loader that + // will be used for the new request (the DESTINATION of the history + // navigation - we want to use the current DocumentLoader to record the + // SOURCE). + DocumentLoader* docLoader = m_frame->loader()->documentLoader(); + ASSERT(docLoader); + m_historyNavigationSourceURLs.add(docLoader->url()); + m_historyNavigationSourceURLs.add(docLoader->originalURL()); + } +} + +void FrameLoaderClientBlackBerry::loadIconExternally(const String& originalPageUrl, const String& finalPageUrl, const String& iconUrl) +{ + m_webPagePrivate->m_client->setIconForUrl(originalPageUrl.utf8().data(), finalPageUrl.utf8().data(), iconUrl.utf8().data()); +} + +void FrameLoaderClientBlackBerry::saveViewStateToItem(HistoryItem* item) +{ + if (!isMainFrame()) + return; + + ASSERT(item); + HistoryItemViewState& viewState = item->viewState(); + if (viewState.shouldSaveViewState) { + viewState.orientation = m_webPagePrivate->mainFrame()->orientation(); + viewState.isZoomToFitScale = m_webPagePrivate->currentScale() == m_webPagePrivate->zoomToFitScale(); + viewState.scale = m_webPagePrivate->currentScale(); + viewState.shouldReflowBlock = m_webPagePrivate->m_shouldReflowBlock; + } +} + +void FrameLoaderClientBlackBerry::restoreViewState() +{ + if (!isMainFrame()) + return; + + HistoryItem* currentItem = m_frame->loader()->history()->currentItem(); + ASSERT(currentItem); + + if (!currentItem) + return; + + // WebPagePrivate is messing up FrameView::wasScrolledByUser() by sending + // scroll events that look like they were user generated all the time. + // + // Even if the user did not scroll, FrameView is gonna think they did. + // So we use our own bookkeeping code to keep track of whether we were + // actually scrolled by the user during load. + // + // If the user did scroll though, all are going to be in agreement about + // that, and the worst thing that could happen is that + // HistoryController::restoreScrollPositionAndViewState calls + // setScrollPosition with the the same point, which is a NOOP. + IntSize contentsSize = currentItem->contentsSize(); + IntPoint scrollPosition = currentItem->scrollPoint(); + if (m_webPagePrivate->m_userPerformedManualScroll) + scrollPosition = m_webPagePrivate->scrollPosition(); + + // We need to reset this variable after the view state has been restored. + m_webPagePrivate->m_didRestoreFromPageCache = false; + HistoryItemViewState& viewState = currentItem->viewState(); + + // Also, try to keep the users zoom if any. + double scale = viewState.scale; + bool shouldReflowBlock = viewState.shouldReflowBlock; + if (m_webPagePrivate->m_userPerformedManualZoom) { + scale = m_webPagePrivate->currentScale(); + shouldReflowBlock = m_webPagePrivate->m_shouldReflowBlock; + } + + bool scrollChanged = scrollPosition != m_webPagePrivate->scrollPosition(); + bool scaleChanged = scale != m_webPagePrivate->currentScale(); + bool reflowChanged = shouldReflowBlock != m_webPagePrivate->m_shouldReflowBlock; + bool orientationChanged = viewState.orientation % 180 != m_webPagePrivate->mainFrame()->orientation() % 180; + + if (!scrollChanged && !scaleChanged && !reflowChanged && !orientationChanged) + return; + + // When rotate happens, only zoom when previous page was zoomToFitScale, otherwise keep old scale. + if (orientationChanged && viewState.isZoomToFitScale) + scale = BlackBerry::Platform::Graphics::Screen::width() * scale / static_cast<double>(BlackBerry::Platform::Graphics::Screen::height()); + m_webPagePrivate->m_backingStore->d->suspendScreenAndBackingStoreUpdates(); // don't flash checkerboard for the setScrollPosition call + m_frame->view()->setContentsSizeFromHistory(contentsSize); + + // Here we need to set scroll position what we asked for. + // So we use ScrollView::setCanOverscroll(true). + bool oldCanOverscroll = m_frame->view()->canOverScroll(); + m_frame->view()->setCanOverscroll(true); + m_webPagePrivate->setScrollPosition(scrollPosition); + m_frame->view()->setCanOverscroll(oldCanOverscroll); + + m_webPagePrivate->m_shouldReflowBlock = viewState.shouldReflowBlock; + + // Will restore updates to backingstore guaranteed! + if (!m_webPagePrivate->zoomAboutPoint(scale, m_frame->view()->scrollPosition(), true /* enforceScaleClamping */, true /*forceRendering*/, true /*isRestoringZoomLevel*/)) { + // If we're already at that scale, then we should still force rendering since + // our scroll position changed. + m_webPagePrivate->m_backingStore->d->renderVisibleContents(); + + // We need to notify the client of the scroll position and content size change(s) above even if we didn't scale. + m_webPagePrivate->notifyTransformedContentsSizeChanged(); + m_webPagePrivate->notifyTransformedScrollChanged(); + } +} + +PolicyAction FrameLoaderClientBlackBerry::decidePolicyForExternalLoad(const ResourceRequest& request, bool isFragmentScroll) +{ + const KURL& url = request.url(); + String pattern = m_webPagePrivate->findPatternStringForUrl(url); + if (!pattern.isEmpty()) { + m_webPagePrivate->m_client->handleStringPattern(pattern.characters(), pattern.length()); + return PolicyIgnore; + } + + if (m_webPagePrivate->m_webSettings->areLinksHandledExternally() + && isMainFrame() + && !request.mustHandleInternally() + && !isFragmentScroll) { + BlackBerry::Platform::NetworkRequest platformRequest; + request.initializePlatformRequest(platformRequest); + m_webPagePrivate->m_client->handleExternalLink(platformRequest, request.anchorText().characters(), request.anchorText().length(), m_clientRedirectIsPending); + return PolicyIgnore; + } + + return PolicyUse; +} + +void FrameLoaderClientBlackBerry::willDeferLoading() +{ + m_deferredJobsTimer->stop(); + + if (!isMainFrame()) + return; + + m_webPagePrivate->willDeferLoading(); +} + +void FrameLoaderClientBlackBerry::didResumeLoading() +{ + if (!m_deferredManualScript.isNull()) + m_deferredJobsTimer->startOneShot(0); + + if (!isMainFrame()) + return; + + m_webPagePrivate->didResumeLoading(); +} + +void FrameLoaderClientBlackBerry::setDeferredManualScript(const KURL& script) +{ + ASSERT(!m_deferredJobsTimer->isActive()); + m_deferredManualScript = script; +} + +void FrameLoaderClientBlackBerry::deferredJobsTimerFired(Timer<FrameLoaderClientBlackBerry>*) +{ + ASSERT(!m_frame->page()->defersLoading()); + + if (!m_deferredManualScript.isNull()) { + // Executing the script will set deferred loading, which could trigger this timer again if a script is set. So clear the script first. + KURL script = m_deferredManualScript; + m_deferredManualScript = KURL(); + + m_frame->script()->executeIfJavaScriptURL(script); + } + + ASSERT(!m_frame->page()->defersLoading()); +} + +void FrameLoaderClientBlackBerry::readyToRender(bool pageIsVisuallyNonEmpty) +{ + // Only send the notification once. + if (!m_sentReadyToRender) { + m_webPagePrivate->m_client->notifyLoadReadyToRender(pageIsVisuallyNonEmpty); + m_sentReadyToRender = true; + } +} + +PassRefPtr<FrameNetworkingContext> FrameLoaderClientBlackBerry::createNetworkingContext() +{ + return FrameNetworkingContextBlackBerry::create(m_frame); +} + +void FrameLoaderClientBlackBerry::authenticationChallenge(const String& realm, String& username, String& password) +{ + WebString webPageUsername; + WebString webPagePassword; + + m_webPagePrivate->m_client->authenticationChallenge(realm.characters(), realm.length(), webPageUsername, webPagePassword); + + username = webPageUsername; + password = webPagePassword; +} + +void FrameLoaderClientBlackBerry::startDownload(const ResourceRequest& request, const String& /*suggestedName*/) +{ + // FIXME: use the suggestedName? + m_webPagePrivate->load(request.url().string().utf8().data(), 0, "GET", BlackBerry::Platform::NetworkRequest::UseProtocolCachePolicy, 0, 0, 0, 0, false, false, true, ""); +} + +void FrameLoaderClientBlackBerry::download(ResourceHandle* handle, const ResourceRequest&, const ResourceRequest&, const ResourceResponse& r) +{ + BlackBerry::Platform::FilterStream* stream = NetworkManager::instance()->streamForHandle(handle); + ASSERT(stream); + + m_webPagePrivate->m_client->downloadRequested(stream, r.suggestedFilename()); +} + +void FrameLoaderClientBlackBerry::dispatchDidReceiveIcon() +{ + String url = m_frame->document()->url().string(); + Image* img = iconDatabase().synchronousIconForPageURL(url, IntSize(10, 10)); + if (!img || !img->data()) + return; + + NativeImageSkia* bitmap = img->nativeImageForCurrentFrame(); + if (!bitmap) + return; + bitmap->lockPixels(); + String iconUrl = iconDatabase().synchronousIconURLForPageURL(url); + m_webPagePrivate->m_client->setFavicon(img->width(), img->height(), (unsigned char*)bitmap->getPixels(), iconUrl.utf8().data()); + bitmap->unlockPixels(); +} + +bool FrameLoaderClientBlackBerry::canCachePage() const +{ + // We won't cache pages containing video or audio. + ASSERT(m_frame->document()); + RefPtr<NodeList> nodeList = m_frame->document()->getElementsByTagName(HTMLNames::videoTag.localName()); + if (nodeList.get()->length() > 0) + return false; + nodeList = m_frame->document()->getElementsByTagName(HTMLNames::audioTag.localName()); + if (nodeList.get()->length() > 0) + return false; + + // The multipart of "multipart/x-mixed-replace" only supports image, correct? + // FIXME: Do we have a better place to handle this case? + nodeList = m_frame->document()->getElementsByTagName(HTMLNames::imgTag.localName()); + for (unsigned i = 0; i < nodeList.get()->length(); ++i) { + HTMLImageElement* node = static_cast<HTMLImageElement*>(nodeList.get()->item(i)); + CachedImage* cachedimage = node ? node->cachedImage() : 0; + if (cachedimage && cachedimage->response().isMultipartPayload()) + return false; + } + return true; +} + +void FrameLoaderClientBlackBerry::didSaveToPageCache() +{ + // When page goes into PageCache, clean up any possible + // document data cache we might have. + m_webPagePrivate->clearDocumentData(m_frame->document()); +} + +void FrameLoaderClientBlackBerry::provisionalLoadStarted() +{ + // We would like to hide the virtual keyboard before it navigates to another page + // so that the scroll offset without keyboard shown will be saved in the history item. + // Then when the user navigates back, it will scroll to the right position. + if (isMainFrame()) + m_webPagePrivate->showVirtualKeyboard(false); +} + +// We don't need to provide the error message string, that will be handled in BrowserErrorPage according to the error code. +ResourceError FrameLoaderClientBlackBerry::cannotShowURLError(const ResourceRequest& request) +{ + // FIXME: Why are we not passing the domain to the ResourceError? See PR #119789. + return ResourceError(String(), WebKitErrorCannotShowURL, request.url().string(), String()); +} + +void FrameLoaderClientBlackBerry::didRestoreFromPageCache() +{ + m_webPagePrivate->m_didRestoreFromPageCache = true; +} + +void FrameLoaderClientBlackBerry::dispatchWillUpdateApplicationCache(const ResourceRequest&) +{ + ASSERT(isMainFrame()); + if (!isMainFrame()) + return; + + m_webPagePrivate->m_client->notifyWillUpdateApplicationCache(); +} + +void FrameLoaderClientBlackBerry::dispatchDidLoadFromApplicationCache(const ResourceRequest&) +{ + ASSERT(isMainFrame()); + if (!isMainFrame()) + return; + + m_webPagePrivate->m_client->notifyDidLoadFromApplicationCache(); +} + +} // WebCore diff --git a/Source/WebKit/blackberry/WebCoreSupport/FrameLoaderClientBlackBerry.h b/Source/WebKit/blackberry/WebCoreSupport/FrameLoaderClientBlackBerry.h new file mode 100644 index 000000000..2983d01ee --- /dev/null +++ b/Source/WebKit/blackberry/WebCoreSupport/FrameLoaderClientBlackBerry.h @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FrameLoaderClientBlackBerry_h +#define FrameLoaderClientBlackBerry_h + +#include "DocumentLoader.h" +#include "Frame.h" +#include "FrameLoaderClient.h" +#include "NotImplemented.h" +#include "Widget.h" + +namespace BlackBerry { +namespace WebKit { +class WebPagePrivate; +} +} + +namespace WebCore { + +class FrameNetworkingContext; +class Geolocation; + +class FrameLoaderClientBlackBerry : public FrameLoaderClient { +public: + FrameLoaderClientBlackBerry(); + ~FrameLoaderClientBlackBerry(); + + void setFrame(Frame* frame, BlackBerry::WebKit::WebPagePrivate* webPagePrivate) { m_frame = frame; m_webPagePrivate = webPagePrivate; } + + int playerId() const; + bool cookiesEnabled() const; + + virtual void frameLoaderDestroyed(); + virtual bool hasWebView() const { return true; } + virtual void makeRepresentation(DocumentLoader*) { notImplemented(); } + virtual void forceLayout() { notImplemented(); } + virtual void forceLayoutForNonHTML() { notImplemented(); } + virtual void setCopiesOnScroll() { notImplemented(); } + virtual void detachedFromParent2(); + virtual void detachedFromParent3() { notImplemented(); } + virtual void assignIdentifierToInitialRequest(long unsigned int, DocumentLoader*, const ResourceRequest&) { notImplemented(); } + virtual void dispatchWillSendRequest(DocumentLoader*, long unsigned int, ResourceRequest&, const ResourceResponse&); + virtual bool shouldUseCredentialStorage(DocumentLoader*, long unsigned int) { notImplemented(); return false; } + virtual void dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, long unsigned int, const AuthenticationChallenge&) { notImplemented(); } + virtual void dispatchDidCancelAuthenticationChallenge(DocumentLoader*, long unsigned int, const AuthenticationChallenge&) { notImplemented(); } + virtual void dispatchDidReceiveResponse(DocumentLoader*, long unsigned int, const ResourceResponse&); + virtual void dispatchDidReceiveContentLength(DocumentLoader*, long unsigned int, int) { notImplemented(); } + virtual void dispatchDidFinishLoading(DocumentLoader*, long unsigned int) { notImplemented(); } + virtual void dispatchDidFailLoading(DocumentLoader*, long unsigned int, const ResourceError&) { notImplemented(); } + virtual bool dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int) { notImplemented(); return false; } + virtual void dispatchDidHandleOnloadEvents(); + virtual void dispatchDidReceiveServerRedirectForProvisionalLoad() { notImplemented(); } + virtual void dispatchDidCancelClientRedirect(); + virtual void dispatchWillPerformClientRedirect(const KURL&, double, double); + virtual void dispatchDidChangeLocationWithinPage(); + virtual void dispatchDidPushStateWithinPage(); + virtual void dispatchDidReplaceStateWithinPage(); + virtual void dispatchDidPopStateWithinPage(); + virtual void dispatchWillClose(); + virtual void dispatchDidReceiveIcon(); + virtual void dispatchDidStartProvisionalLoad(); + virtual void dispatchDidReceiveTitle(const StringWithDirection&); + virtual void setTitle(const StringWithDirection& title, const KURL&); + virtual void dispatchDidCommitLoad(); + virtual void dispatchDidFailProvisionalLoad(const ResourceError&); + virtual void dispatchDidFailLoad(const ResourceError&); + virtual void dispatchDidFinishDocumentLoad(); + virtual void dispatchDidFinishLoad(); + virtual void dispatchDidFirstLayout() { notImplemented(); } + virtual void dispatchDidFirstVisuallyNonEmptyLayout(); + virtual Frame* dispatchCreatePage(const NavigationAction&); + virtual void dispatchShow() { notImplemented(); } + + virtual void dispatchDecidePolicyForResponse(FramePolicyFunction, const ResourceResponse&, const ResourceRequest&); + virtual void dispatchDecidePolicyForNewWindowAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName); + virtual void dispatchDecidePolicyForNavigationAction(FramePolicyFunction, const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>); + virtual void cancelPolicyCheck(); + virtual void dispatchUnableToImplementPolicy(const ResourceError&) { notImplemented(); } + virtual void dispatchWillSubmitForm(FramePolicyFunction, PassRefPtr<FormState>); + virtual void dispatchDidLoadMainResource(DocumentLoader*) { notImplemented(); } + virtual void revertToProvisionalState(DocumentLoader*) { notImplemented(); } + virtual void setMainDocumentError(DocumentLoader*, const ResourceError&); + virtual void postProgressStartedNotification(); + virtual void postProgressEstimateChangedNotification(); + virtual void postProgressFinishedNotification(); + virtual void setMainFrameDocumentReady(bool) { notImplemented(); } + virtual void startDownload(const ResourceRequest&, const String& suggestedName = String()); + virtual void willChangeTitle(DocumentLoader*) { notImplemented(); } + virtual void didChangeTitle(DocumentLoader*) { notImplemented(); } + virtual void committedLoad(DocumentLoader*, const char*, int); + virtual void finishedLoading(DocumentLoader*); + virtual void updateGlobalHistory() { notImplemented(); } + virtual void updateGlobalHistoryRedirectLinks() { notImplemented(); } + virtual bool shouldGoToHistoryItem(HistoryItem*) const; + virtual bool shouldStopLoadingForHistoryItem(HistoryItem*) const; + virtual void dispatchDidAddBackForwardItem(HistoryItem*) const; + virtual void dispatchDidRemoveBackForwardItem(HistoryItem*) const; + virtual void dispatchDidChangeBackForwardIndex() const; + virtual void dispatchWillUpdateApplicationCache(const ResourceRequest&); + virtual void dispatchDidLoadFromApplicationCache(const ResourceRequest&); + virtual void didDisplayInsecureContent() { notImplemented(); } + virtual void didRunInsecureContent(SecurityOrigin*, const KURL&) { notImplemented(); } + virtual ResourceError interruptedForPolicyChangeError(const ResourceRequest&) { notImplemented(); return ResourceError(emptyString(), 0, emptyString(), emptyString()); } + virtual ResourceError cancelledError(const ResourceRequest&) { notImplemented(); return ResourceError(emptyString(), 0, emptyString(), emptyString()); } + virtual ResourceError blockedError(const ResourceRequest&) { notImplemented(); return ResourceError(emptyString(), 0, emptyString(), emptyString()); } + virtual ResourceError cannotShowURLError(const ResourceRequest&); + virtual ResourceError interruptForPolicyChangeError(const ResourceRequest&) { notImplemented(); return ResourceError(emptyString(), 0, emptyString(), emptyString()); } + virtual ResourceError cannotShowMIMETypeError(const ResourceResponse&) { notImplemented(); return ResourceError(emptyString(), 0, emptyString(), emptyString()); } + virtual ResourceError fileDoesNotExistError(const ResourceResponse&) { notImplemented(); return ResourceError(emptyString(), 0, emptyString(), emptyString()); } + virtual ResourceError pluginWillHandleLoadError(const ResourceResponse&) { notImplemented(); return ResourceError(emptyString(), 0, emptyString(), emptyString()); } + virtual bool shouldFallBack(const ResourceError&) { notImplemented(); return false; } + virtual bool canHandleRequest(const ResourceRequest&) const; + virtual bool canShowMIMEType(const String&) const; + virtual bool canShowMIMETypeAsHTML(const String&) const; + virtual bool representationExistsForURLScheme(const String&) const { notImplemented(); return false; } + virtual String generatedMIMETypeForURLScheme(const String&) const { notImplemented(); return String(); } + virtual void frameLoadCompleted() { notImplemented(); } + virtual void saveViewStateToItem(HistoryItem*); + virtual void restoreViewState(); + virtual void provisionalLoadStarted(); + virtual void didFinishLoad() { notImplemented(); } + virtual void prepareForDataSourceReplacement() { notImplemented(); } + virtual PassRefPtr<DocumentLoader> createDocumentLoader(const ResourceRequest&, const SubstituteData&); + virtual void setTitle(const String&, const KURL&) { notImplemented(); } + virtual String userAgent(const KURL&); + virtual void savePlatformDataToCachedFrame(CachedFrame*) { notImplemented(); } + virtual void transitionToCommittedFromCachedFrame(CachedFrame*) { notImplemented(); } + virtual void transitionToCommittedForNewPage(); + virtual bool canCachePage() const; + virtual void didSaveToPageCache(); + virtual void didRestoreFromPageCache(); + virtual void dispatchDidBecomeFrameset(bool) { } + virtual void download(ResourceHandle*, const ResourceRequest&, const ResourceRequest&, const ResourceResponse&); + virtual PassRefPtr<Frame> createFrame(const KURL&, const String&, HTMLFrameOwnerElement*, const String&, bool, int, int); + virtual void didTransferChildFrameToNewDocument(Page*); + virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool); + virtual void redirectDataToPlugin(Widget*); + virtual PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL&, const Vector<String>&, const Vector<String>&) { notImplemented(); return 0; } + + virtual ObjectContentType objectContentType(const KURL&, const String& mimeType, bool shouldPreferPlugInsForImages); + virtual String overrideMediaType() const { notImplemented(); return String(); } + virtual void dispatchDidClearWindowObjectInWorld(DOMWrapperWorld*); + virtual void documentElementAvailable() { notImplemented(); } + virtual void didPerformFirstNavigation() const { notImplemented(); } + virtual void registerForIconNotification(bool) { notImplemented(); } + + virtual bool shouldLoadIconExternally() { return false; } + virtual void loadIconExternally(const String& originalPageUrl, const String& finalPageUrl, const String& iconUrl); + + virtual void didDetectXSS(const KURL&, bool) { } + virtual void transferLoadingResourceFromPage(ResourceLoader*, const ResourceRequest&, Page*); + virtual void didTransferChildFrameToNewDocument() { notImplemented(); }; + virtual void dispatchDidChangeIcons(IconType) { notImplemented(); }; + virtual void dispatchWillSendSubmitEvent(HTMLFormElement*) { notImplemented(); }; + + virtual void willDeferLoading(); + virtual void didResumeLoading(); + virtual void authenticationChallenge(const String& realm, String& username, String& password); + + virtual PassRefPtr<FrameNetworkingContext> createNetworkingContext(); + + // Schedule a script that was loaded manually by the user (eg. a + // bookmarklet) while page loading was deferred. + void setDeferredManualScript(const KURL&); + + void readyToRender(bool pageIsVisuallyNonEmpty); + + void doPendingFragmentScroll(); + + // Used to stop media files from loading because we don't need to have the entire file loaded by WebKit. + void setCancelLoadOnNextData() { m_cancelLoadOnNextData = true; } + bool shouldCancelLoadOnNextData() const { return m_cancelLoadOnNextData; } + + void suppressChildFrameCreation() { m_childFrameCreationSuppressed = true; } + +private: + void receivedData(const char*, int, const String&); + void didFinishOrFailLoading(const ResourceError&); + bool isMainFrame() const; + + void invalidateBackForwardList() const; + void notifyBackForwardListChanged() const; + + PolicyAction decidePolicyForExternalLoad(const ResourceRequest &, bool isFragmentScroll); + void delayPolicyCheckUntilFragmentExists(const String& fragment, FramePolicyFunction); + + void deferredJobsTimerFired(Timer<FrameLoaderClientBlackBerry>*); + + Frame* m_frame; + ResourceError m_loadError; + BlackBerry::WebKit::WebPagePrivate* m_webPagePrivate; + + Timer<FrameLoaderClientBlackBerry>* m_deferredJobsTimer; + KURL m_deferredManualScript; + Geolocation* m_geolocation; + bool m_sentReadyToRender; + + FramePolicyFunction m_pendingFragmentScrollPolicyFunction; + String m_pendingFragmentScroll; + + bool m_loadingErrorPage; + bool m_clientRedirectIsPending; + bool m_childFrameCreationSuppressed; + + // This set includes the original and final urls for server redirects. + HashSet<KURL> m_historyNavigationSourceURLs; + HashSet<KURL> m_redirectURLsToSkipDueToHistoryNavigation; + + // Plugin view to redirect data to. + PluginView* m_pluginView; + bool m_hasSentResponseToPlugin; + + // Used to stop media files from loading because we don't need to have the entire file loaded by WebKit. + bool m_cancelLoadOnNextData; +}; + +} // WebCore + +#endif // FrameLoaderClientBlackBerry_h diff --git a/Source/WebKit/blackberry/WebCoreSupport/JavaScriptDebuggerBlackBerry.cpp b/Source/WebKit/blackberry/WebCoreSupport/JavaScriptDebuggerBlackBerry.cpp new file mode 100644 index 000000000..ffe7e9383 --- /dev/null +++ b/Source/WebKit/blackberry/WebCoreSupport/JavaScriptDebuggerBlackBerry.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#if ENABLE(JAVASCRIPT_DEBUGGER) +#include "JavaScriptDebuggerBlackBerry.h" + +#include "JavaScriptCallFrame.h" +#include "PageScriptDebugServer.h" +#include "PlatformString.h" +#include "ScriptBreakpoint.h" +#include "SourceCode.h" +#include "WebPage_p.h" + +namespace WebCore { + +JavaScriptDebuggerBlackBerry::JavaScriptDebuggerBlackBerry(BlackBerry::WebKit::WebPagePrivate* webPagePrivate) + : m_webPagePrivate(webPagePrivate) + , m_debugServer(PageScriptDebugServer::shared()) +{ + start(); +} + +JavaScriptDebuggerBlackBerry::~JavaScriptDebuggerBlackBerry() +{ + stop(); +} + +void JavaScriptDebuggerBlackBerry::start() +{ + m_debugServer.addListener(this, m_webPagePrivate->m_page); +} + +void JavaScriptDebuggerBlackBerry::stop() +{ + m_debugServer.removeListener(this, m_webPagePrivate->m_page); +} + +void JavaScriptDebuggerBlackBerry::addBreakpoint(const unsigned short* url, unsigned urlLength, int lineNumber, const unsigned short* condition, unsigned conditionLength) +{ + if (!url || !urlLength) + return; + if (!m_currentCallFrame) + return; + + String sourceString(url, urlLength); + String conditionString(condition, conditionLength); + int actualLineNumber; + m_debugServer.setBreakpoint(sourceString, ScriptBreakpoint(lineNumber, 0, conditionString), &lineNumber, &actualLineNumber); +} + +void JavaScriptDebuggerBlackBerry::updateBreakpoint(const unsigned short* url, unsigned urlLength, int lineNumber, const unsigned short* condition, unsigned conditionLength) +{ + if (!url || !urlLength) + return; + if (!m_currentCallFrame) + return; + + String sourceString(url, urlLength); + String conditionString(condition, conditionLength); + int actualLineNumber; + m_debugServer.setBreakpoint(sourceString, ScriptBreakpoint(lineNumber, 0, conditionString), &lineNumber, &actualLineNumber); +} + + +void JavaScriptDebuggerBlackBerry::removeBreakpoint(const unsigned short* url, unsigned urlLength, int lineNumber) +{ + if (!url || !urlLength) + return; + if (!m_currentCallFrame) + return; + + String sourceString(url, urlLength); + sourceString += ":" + lineNumber; + m_debugServer.removeBreakpoint(sourceString); +} + + +bool JavaScriptDebuggerBlackBerry::pauseOnExceptions() +{ + return m_debugServer.pauseOnExceptionsState() == ScriptDebugServer::PauseOnAllExceptions; +} + +void JavaScriptDebuggerBlackBerry::setPauseOnExceptions(bool pause) +{ + m_debugServer.setPauseOnExceptionsState(pause ? ScriptDebugServer::PauseOnAllExceptions : ScriptDebugServer::DontPauseOnExceptions); +} + +void JavaScriptDebuggerBlackBerry::pauseInDebugger() +{ + m_debugServer.setPauseOnNextStatement(true); +} + +void JavaScriptDebuggerBlackBerry::resumeDebugger() +{ + m_debugServer.continueProgram(); +} + +void JavaScriptDebuggerBlackBerry::stepOverStatementInDebugger() +{ + m_debugServer.stepOverStatement(); +} + +void JavaScriptDebuggerBlackBerry::stepIntoStatementInDebugger() +{ + m_debugServer.stepIntoStatement(); +} + +void JavaScriptDebuggerBlackBerry::stepOutOfFunctionInDebugger() +{ + m_debugServer.stepOutOfFunction(); +} + +void JavaScriptDebuggerBlackBerry::didParseSource(const String& sourceID, const Script& script) +{ + m_webPagePrivate->m_client->javascriptSourceParsed(script.url.characters(), script.url.length(), script.source.characters(), script.source.length()); +} + +void JavaScriptDebuggerBlackBerry::failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage) +{ + m_webPagePrivate->m_client->javascriptParsingFailed(url.impl()->characters(), url.length(), errorMessage.impl()->characters(), errorMessage.length(), errorLine); +} + +void JavaScriptDebuggerBlackBerry::didPause(ScriptState*, const ScriptValue& callFrames, const ScriptValue& exception) +{ + String stacks; + + m_currentCallFrame = m_debugServer.currentCallFrame(); + JavaScriptCallFrame* frame = m_currentCallFrame; + + while (frame && frame->isValid()) { + JSC::SourceProvider* provider = reinterpret_cast<JSC::SourceProvider*>(frame->sourceID()); + String url(provider->url().characters(), provider->url().length()); + if (url.length()) + stacks += url; + stacks += ": "; + + if (frame->type() == JSC::DebuggerCallFrame::FunctionType) { + String name = frame->functionName(); + if (name.length()) + stacks += name; + } + stacks += "(): "; + + String line = String::number(frame->line()); + stacks += line + "\n"; + + frame = frame->caller(); + } + + m_webPagePrivate->m_client->javascriptPaused(reinterpret_cast<const unsigned short*>(stacks.characters()), stacks.length()); +} + +void JavaScriptDebuggerBlackBerry::didContinue() +{ + m_currentCallFrame = 0; + m_webPagePrivate->m_client->javascriptContinued(); +} + +} // namespace WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) diff --git a/Source/WebKit/blackberry/WebCoreSupport/JavaScriptDebuggerBlackBerry.h b/Source/WebKit/blackberry/WebCoreSupport/JavaScriptDebuggerBlackBerry.h new file mode 100644 index 000000000..2f511b2a3 --- /dev/null +++ b/Source/WebKit/blackberry/WebCoreSupport/JavaScriptDebuggerBlackBerry.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ + * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef JavaScriptDebuggerBlackBerry_h +#define JavaScriptDebuggerBlackBerry_h + +#if ENABLE(JAVASCRIPT_DEBUGGER) + +#include "ScriptDebugListener.h" + +namespace BlackBerry { +namespace WebKit { +class WebPagePrivate; +} +} + +namespace WebCore { + +class JavaScriptCallFrame; +class PageScriptDebugServer; + +class JavaScriptDebuggerBlackBerry : public ScriptDebugListener { +public: + JavaScriptDebuggerBlackBerry(BlackBerry::WebKit::WebPagePrivate*); + ~JavaScriptDebuggerBlackBerry(); + + void addBreakpoint(const unsigned short* url, unsigned urlLength, int lineNumber, const unsigned short* condition, unsigned conditionLength); + void updateBreakpoint(const unsigned short* url, unsigned urlLength, int lineNumber, const unsigned short* condition, unsigned conditionLength); + void removeBreakpoint(const unsigned short* url, unsigned urlLength, int lineNumber); + + bool pauseOnExceptions(); + void setPauseOnExceptions(bool); + + void pauseInDebugger(); + void resumeDebugger(); + + void stepOverStatementInDebugger(); + void stepIntoStatementInDebugger(); + void stepOutOfFunctionInDebugger(); + + // From ScriptDebugListener + virtual void didParseSource(const String& sourceID, const Script&); + virtual void failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage); + virtual void didPause(ScriptState*, const ScriptValue& callFrames, const ScriptValue& exception); + virtual void didContinue(); + +protected: + void start(); + void stop(); + +private: + BlackBerry::WebKit::WebPagePrivate* m_webPagePrivate; + PageScriptDebugServer& m_debugServer; + + JavaScriptCallFrame* m_currentCallFrame; +}; + +} // WebCore + +#endif // ENABLE(JAVASCRIPT_DEBUGGER) +#endif // JavaScriptDebuggerBlackBerry_h diff --git a/Source/WebKit/blackberry/WebCoreSupport/inspectorBB.html b/Source/WebKit/blackberry/WebCoreSupport/inspectorBB.html new file mode 100644 index 000000000..5f692197f --- /dev/null +++ b/Source/WebKit/blackberry/WebCoreSupport/inspectorBB.html @@ -0,0 +1,64 @@ +<!-- +Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. +Copyright (C) 2011, 2012 Research In Motion Ltd. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY APPLE 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 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. +--> +<!DOCTYPE html> +<html> + <head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> + <link rel="stylesheet" type="text/css" href="audits.css"> + <link rel="stylesheet" type="text/css" href="dataGrid.css"> + <link rel="stylesheet" type="text/css" href="goToLineDialog.css"> + <link rel="stylesheet" type="text/css" href="heapProfiler.css"> + <link rel="stylesheet" type="text/css" href="inspector.css"> + <link rel="stylesheet" type="text/css" href="inspectorCommon.css"> + <link rel="stylesheet" type="text/css" href="inspectorSyntaxHighlight.css"> + <link rel="stylesheet" type="text/css" href="networkPanel.css"> + <link rel="stylesheet" type="text/css" href="helpScreen.css"> + <link rel="stylesheet" type="text/css" href="popover.css"> + <link rel="stylesheet" type="text/css" href="textViewer.css"> + <script type="text/javascript" src="javascript.js"></script> + </head> + <body class="detached"> + <div id="toolbar"> + <div class="toolbar-item close-left"><button id="close-button-left"></button></div> + <div id="toolbar-controls"> + <div class="toolbar-item"><button id="toolbar-dropdown-arrow" class="toolbar-label">»</button></div> + <div class="toolbar-item hidden" id="search-results-matches"></div> + <div class="toolbar-item toolbar-search-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div> + <div class="toolbar-item close-right"><button id="close-button-right"></button></div> + </div> + </div> + <div id="main"> + <div id="main-panels" spellcheck="false"></div> + <div id="main-status-bar" class="status-bar"><div id="anchored-status-bar-items"><div id="counters"><div id="error-warning-count" class="hidden"></div></div></div></div> + </div> + <div id="drawer"> + <div id="console-view"><div id="console-messages" class="monospace"><div id="console-prompt" spellcheck="false"><br></div></div></div> + <div id="drawer-status-bar" class="status-bar"><div id="other-drawer-status-bar-items"><button id="clear-console-status-bar-item" class="status-bar-item clear-status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><select id="console-context" class="status-bar-item"></select><div id="console-filter" class="scope-bar status-bar-item"></div></div></div> + </div> +</body> +</html> diff --git a/Source/WebKit/blackberry/WebCoreSupport/inspectorBB.js b/Source/WebKit/blackberry/WebCoreSupport/inspectorBB.js new file mode 100644 index 000000000..3017e0a58 --- /dev/null +++ b/Source/WebKit/blackberry/WebCoreSupport/inspectorBB.js @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +var context = {}; +(function () { + Preferences.ignoreWhitespace = false; + Preferences.samplingCPUProfiler = true; + Preferences.debuggerAlwaysEnabled = true; + Preferences.profilerAlwaysEnabled = true; + Preferences.canEditScriptSource = false; + Preferences.onlineDetectionEnabled = false; + Preferences.nativeInstrumentationEnabled = true; + // FIXME: Turn this to whatever the value of --enable-file-system for chrome. + Preferences.fileSystemEnabled = false; + Preferences.canClearCacheAndCookies = true; + Preferences.showCookiesTab = true; +})(); +InspectorFrontendHost.copyText = function(tmp) { + var encoded = encodeURI(tmp); + var text = 'data:text/plain;charset=utf-8,' + encoded; + window.open(text, "_blank"); +} diff --git a/Source/WebKit/blackberry/WebKitSupport/BackingStoreClient.cpp b/Source/WebKit/blackberry/WebKitSupport/BackingStoreClient.cpp new file mode 100644 index 000000000..c7de7716c --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/BackingStoreClient.cpp @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2009, 2010, 2011 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "BackingStoreClient.h" + +#include "BackingStore.h" +#include "BackingStore_p.h" +#include "FloatPoint.h" +#include "FocusController.h" +#include "Frame.h" +#include "FrameView.h" +#include "HTMLFrameOwnerElement.h" +#include "Page.h" +#include "RenderBox.h" +#include "WebPage_p.h" + +// FIXME: Leaving the below lines commented out as a reference for us to soon be sure if we need these +// methods and class variables be moved from WebPage to BackingStoreClient. +// Notification methods that deliver changes to the real geometry of the device as specified above. +// void notifyTransformChanged(); +// void notifyTransformedContentsSizeChanged(); +// void notifyTransformedScrollChanged(); +// m_overflowExceedsContentsSize = true; +// haspendingscrollevent + +using namespace WebCore; + +namespace BlackBerry { +namespace WebKit { + +static inline IntSize pointToSize(const IntPoint& point) +{ + return IntSize(point.x(), point.y()); +} + +BackingStoreClient* BackingStoreClient::create(Frame* frame, Frame* parentFrame, WebPage* parentPage) +{ + ASSERT(parentPage); + ASSERT(frame->view()); + + // FIXME: We do not support inner frames for now. + if (parentFrame) + return 0; + + BackingStoreClient* parentBackingStoreClient + = parentFrame + ? parentPage->d->backingStoreClientForFrame(parentFrame) + : 0; + + // If this frame has a parent with no backingstore then just stop since + // our frame heirarchy is done. + if (parentFrame && !parentBackingStoreClient) + return 0; + + BackingStoreClient* it = new BackingStoreClient(frame, parentFrame, parentPage); + ASSERT(it); + + // Frame -> BackingStoreClient mapping is controlled by the Page. + parentPage->d->addBackingStoreClientForFrame(frame, it); + + // Add the backing store client to the child list of its parent. + if (parentBackingStoreClient) + parentBackingStoreClient->addChild(it); + + return it; +} + +BackingStoreClient::BackingStoreClient(Frame* frame, Frame* parentFrame, WebPage* parentPage) + : m_frame(frame) + , m_webPage(parentPage) + , m_backingStore(0) + , m_parent(0) + , m_isClientGeneratedScroll(false) + , m_isScrollNotificationSuppressed(false) +{ + UNUSED_PARAM(parentFrame); + m_backingStore = new BackingStore(m_webPage, this); +} + +BackingStoreClient::~BackingStoreClient() +{ + m_webPage->d->removeBackingStoreClientForFrame(m_frame); + + delete m_backingStore; + m_backingStore = 0; + m_frame = 0; +} + +void BackingStoreClient::addChild(BackingStoreClient* child) +{ + ASSERT(child); + child->m_parent = this; +} + +WTF::Vector <BackingStoreClient*> BackingStoreClient::children() const +{ + WTF::Vector<BackingStoreClient*> children; + for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { + BlackBerry::WebKit::BackingStoreClient* client = + m_webPage->d->backingStoreClientForFrame(child); + + if (client) + children.append(client); + } + + return children; +} + +IntRect BackingStoreClient::absoluteRect() const +{ + IntRect rect = IntRect(IntPoint::zero(), viewportSize()); + + if (!isMainFrame()) { + // It is possible that the owner HTML element has been removed at this point, + // especially when the frame is loading a JavaScript URL. + if (Element* elt = m_frame->ownerElement()) { + if (RenderBox* obj = elt->renderBox()) + rect.move(obj->borderLeft() + obj->paddingLeft(), obj->borderTop() + obj->paddingTop()); + } + } + + Frame* frame = m_frame; + while (frame) { + if (Element* element = static_cast<Element*>(frame->ownerElement())) { + do { + rect.move(element->offsetLeft(), element->offsetTop()); + } while ((element = element->offsetParent())); + } + + if ((frame = frame->tree()->parent())) + rect.move((-frame->view()->scrollOffset())); + } + + return rect; +} + +IntRect BackingStoreClient::transformedAbsoluteRect() const +{ + return m_webPage->d->mapToTransformed(absoluteRect()); +} + +IntPoint BackingStoreClient::absoluteLocation() const +{ + return absoluteRect().location(); +} + +IntPoint BackingStoreClient::transformedAbsoluteLocation() const +{ + return m_webPage->d->mapToTransformed(transformedAbsoluteRect()).location(); +} + +IntPoint BackingStoreClient::scrollPosition() const +{ + ASSERT(m_frame); + return m_frame->view()->scrollPosition() - pointToSize(m_frame->view()->minimumScrollPosition()); +} + +IntPoint BackingStoreClient::transformedScrollPosition() const +{ + return m_webPage->d->mapToTransformed(scrollPosition()); +} + +void BackingStoreClient::setScrollPosition(const IntPoint& pos) +{ + ASSERT(m_frame->view()); + if (pos == scrollPosition()) + return; + + // We set a flag here to note that this scroll operation was originated + // within the BlackBerry-specific layer of WebKit and not by WebCore. + // This flag is checked in checkOriginOfCurrentScrollOperation() to decide + // whether to notify the client of the current scroll operation. This is + // why it is important that all scroll operations that originate within + // BlackBerry-specific code are encapsulated here and that callers of this + // method also directly or indirectly call notifyTransformedScrollChanged(). + m_isScrollNotificationSuppressed = true; + m_frame->view()->setScrollPosition(pos + pointToSize(m_frame->view()->minimumScrollPosition())); + m_isScrollNotificationSuppressed = false; +} + +IntPoint BackingStoreClient::maximumScrollPosition() const +{ + ASSERT(m_frame->view()); + return m_frame->view()->maximumScrollPosition() - pointToSize(m_frame->view()->minimumScrollPosition()); +} + +IntPoint BackingStoreClient::transformedMaximumScrollPosition() const +{ + return m_webPage->d->mapToTransformed(maximumScrollPosition()); +} + +IntSize BackingStoreClient::actualVisibleSize() const +{ + return m_webPage->d->mapFromTransformed(transformedActualVisibleSize()); +} + +IntSize BackingStoreClient::transformedActualVisibleSize() const +{ + if (isMainFrame()) + return m_webPage->d->transformedActualVisibleSize(); + + return transformedViewportSize(); +} + +IntSize BackingStoreClient::viewportSize() const +{ + ASSERT(m_frame->view()); + if (isMainFrame()) + return m_webPage->d->viewportSize(); + + return m_frame->view()->visibleContentRect().size(); +} + +IntSize BackingStoreClient::transformedViewportSize() const +{ + if (isMainFrame()) + return m_webPage->d->transformedViewportSize(); + + ASSERT(m_frame->view()); + const IntSize untransformedViewportSize = m_frame->view()->visibleContentRect().size(); + const FloatPoint transformedBottomRight = m_webPage->d->m_transformationMatrix->mapPoint( + FloatPoint(untransformedViewportSize.width(), untransformedViewportSize.height())); + return IntSize(floorf(transformedBottomRight.x()), floorf(transformedBottomRight.y())); +} + +IntRect BackingStoreClient::visibleContentsRect() const +{ + ASSERT(m_frame->view()); + IntRect visibleContentRect = m_frame->view()->visibleContentRect(); + if (isMainFrame()) + return visibleContentRect; + + IntPoint offset = absoluteLocation(); + visibleContentRect.move(offset.x(), offset.y()); + if (m_parent) + visibleContentRect.intersect(m_parent->visibleContentsRect()); + + return visibleContentRect; +} + +IntRect BackingStoreClient::transformedVisibleContentsRect() const +{ + // Usually this would be mapToTransformed(visibleContentsRect()), but + // that results in rounding errors because we already set the WebCore + // viewport size from our original transformedViewportSize(). + // Instead, we only transform the scroll position and take the + // viewport size as it is, which ensures that e.g. blitting operations + // always cover the whole widget/screen. + IntRect visibleContentsRect = IntRect(transformedScrollPosition(), transformedViewportSize()); + if (isMainFrame()) + return visibleContentsRect; + + IntPoint offset = transformedAbsoluteLocation(); + visibleContentsRect.move(offset.x(), offset.y()); + return visibleContentsRect; +} + +IntSize BackingStoreClient::contentsSize() const +{ + ASSERT(m_frame->view()); + return m_frame->view()->contentsSize(); +} + +IntSize BackingStoreClient::transformedContentsSize() const +{ + // mapToTransformed() functions use this method to crop their results, + // so we can't make use of them here. While we want rounding inside page + // boundaries to extend rectangles and round points, we need to crop the + // contents size to the floored values so that we don't try to display + // or report points that are not fully covered by the actual float-point + // contents rectangle. + const IntSize untransformedContentsSize = contentsSize(); + const FloatPoint transformedBottomRight = m_webPage->d->m_transformationMatrix->mapPoint( + FloatPoint(untransformedContentsSize.width(), untransformedContentsSize.height())); + return IntSize(floorf(transformedBottomRight.x()), floorf(transformedBottomRight.y())); +} + +void BackingStoreClient::clipToTransformedContentsRect(IntRect& rect) const +{ + // FIXME: Needs to proper translate coordinates here? + rect.intersect(IntRect(IntPoint::zero(), transformedContentsSize())); +} + +IntPoint BackingStoreClient::mapFromContentsToViewport(const IntPoint& point) const +{ + const IntPoint scrollPosition = this->scrollPosition(); + return IntPoint(point.x() - scrollPosition.x(), point.y() - scrollPosition.y()); +} + +IntPoint BackingStoreClient::mapFromViewportToContents(const IntPoint& point) const +{ + const IntPoint scrollPosition = this->scrollPosition(); + return IntPoint(point.x() + scrollPosition.x(), point.y() + scrollPosition.y()); +} + +IntRect BackingStoreClient::mapFromContentsToViewport(const IntRect& rect) const +{ + return IntRect(mapFromContentsToViewport(rect.location()), rect.size()); +} + +IntRect BackingStoreClient::mapFromViewportToContents(const IntRect& rect) const +{ + return IntRect(mapFromViewportToContents(rect.location()), rect.size()); +} + +IntPoint BackingStoreClient::mapFromTransformedContentsToTransformedViewport(const IntPoint& point) const +{ + const IntPoint scrollPosition = transformedScrollPosition(); + return IntPoint(point.x() - scrollPosition.x(), point.y() - scrollPosition.y()); +} + +IntPoint BackingStoreClient::mapFromTransformedViewportToTransformedContents(const IntPoint& point) const +{ + const IntPoint scrollPosition = transformedScrollPosition(); + return IntPoint(point.x() + scrollPosition.x(), point.y() + scrollPosition.y()); +} + +IntRect BackingStoreClient::mapFromTransformedContentsToTransformedViewport(const IntRect& rect) const +{ + return IntRect(mapFromTransformedContentsToTransformedViewport(rect.location()), rect.size()); +} + +IntRect BackingStoreClient::mapFromTransformedViewportToTransformedContents(const IntRect& rect) const +{ + return IntRect(mapFromTransformedViewportToTransformedContents(rect.location()), rect.size()); +} + +WebPagePrivate::LoadState BackingStoreClient::loadState() const +{ + // FIXME: Does it need to call WebPage's? + return m_webPage->d->loadState(); +} + +bool BackingStoreClient::isLoading() const +{ + // FIXME: Does it need to call WebPage's? + return m_webPage->d->isLoading(); +} + +bool BackingStoreClient::isFocused() const +{ + return m_frame && m_frame->page() && m_frame->page()->focusController() + && m_frame->page()->focusController()->focusedFrame() == m_frame; +} + +bool BackingStoreClient::scrollsHorizontally() const +{ + return transformedActualVisibleSize().width() < transformedContentsSize().width(); +} + +bool BackingStoreClient::scrollsVertically() const +{ + return transformedActualVisibleSize().height() < transformedContentsSize().height(); +} + +bool BackingStoreClient::isClientGeneratedScroll() const +{ + return m_isClientGeneratedScroll; +} + +void BackingStoreClient::setIsClientGeneratedScroll(bool flag) +{ + m_isClientGeneratedScroll = flag; +} + +bool BackingStoreClient::isScrollNotificationSuppressed() const +{ + return m_isScrollNotificationSuppressed; +} + +void BackingStoreClient::setIsScrollNotificationSuppressed(bool flag) +{ + m_isScrollNotificationSuppressed = flag; +} + +void BackingStoreClient::checkOriginOfCurrentScrollOperation() +{ + // This is called via ChromeClientBlackBerry::scroll in order to check the origin + // of the current scroll operation to decide whether to notify the client. + // If the current scroll operation was initiated internally by WebCore itself + // either via JavaScript, back/forward or otherwise then we need to go ahead + // and notify the client of this change. + if (isScrollNotificationSuppressed()) + return; + + if (isMainFrame()) + m_webPage->d->notifyTransformedScrollChanged(); + else + m_backingStore->d->scrollChanged(transformedScrollPosition()); +} + +} +} diff --git a/Source/WebKit/blackberry/WebKitSupport/BackingStoreClient.h b/Source/WebKit/blackberry/WebKitSupport/BackingStoreClient.h new file mode 100644 index 000000000..42b572104 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/BackingStoreClient.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2009, 2010, 2011 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BackingStoreClient_h +#define BackingStoreClient_h + +#include "WebPage_p.h" +#include <wtf/Vector.h> + +namespace WebCore { +class FloatPoint; +class Frame; +class IntPoint; +class IntSize; +class IntRect; +} + +namespace BlackBerry { +namespace WebKit { + +class BackingStore; +class WebPagePrivate; + +class BackingStoreClient { +public: + static BackingStoreClient* create(WebCore::Frame*, WebCore::Frame* parentFrame, WebPage* parentPage); + ~BackingStoreClient(); + + BackingStore* backingStore() const { return m_backingStore; } + WebCore::Frame* frame() const { return m_frame; } + bool isMainFrame() const { return m_frame == m_webPage->d->m_mainFrame; } + + void addChild(BackingStoreClient* child); + WTF::Vector <BackingStoreClient*> children() const; + BackingStoreClient* parent() const { return m_parent; } + + WebCore::IntPoint absoluteLocation() const; + WebCore::IntPoint transformedAbsoluteLocation() const; + WebCore::IntRect absoluteRect() const; + WebCore::IntRect transformedAbsoluteRect() const; + + // scroll position returned is in transformed coordinates + WebCore::IntPoint scrollPosition() const; + WebCore::IntPoint maximumScrollPosition() const; + // scroll position provided should be in transformed coordinates + void setScrollPosition(const WebCore::IntPoint&); + + WebCore::IntPoint transformedScrollPosition() const; + WebCore::IntPoint transformedMaximumScrollPosition() const; + + WebCore::IntSize actualVisibleSize() const; + WebCore::IntSize transformedActualVisibleSize() const; + + WebCore::IntSize viewportSize() const; + WebCore::IntSize transformedViewportSize() const; + + WebCore::IntRect visibleContentsRect() const; + WebCore::IntRect transformedVisibleContentsRect() const; + + WebCore::IntSize contentsSize() const; + WebCore::IntSize transformedContentsSize() const; + + /* Generic conversions of points, rects, relative to and from contents and viewport*/ + WebCore::IntPoint mapFromContentsToViewport(const WebCore::IntPoint&) const; + WebCore::IntPoint mapFromViewportToContents(const WebCore::IntPoint&) const; + WebCore::IntRect mapFromContentsToViewport(const WebCore::IntRect&) const; + WebCore::IntRect mapFromViewportToContents(const WebCore::IntRect&) const; + + /* Generic conversions of points, rects, relative to and from transformed contents and transformed viewport*/ + WebCore::IntPoint mapFromTransformedContentsToTransformedViewport(const WebCore::IntPoint&) const; + WebCore::IntPoint mapFromTransformedViewportToTransformedContents(const WebCore::IntPoint&) const; + WebCore::IntRect mapFromTransformedContentsToTransformedViewport(const WebCore::IntRect&) const; + WebCore::IntRect mapFromTransformedViewportToTransformedContents(const WebCore::IntRect&) const; + + void clipToTransformedContentsRect(WebCore::IntRect&) const; + + bool isLoading() const; + WebPagePrivate::LoadState loadState() const; + + bool isFocused() const; + + bool scrollsHorizontally() const; + bool scrollsVertically() const; + + bool isClientGeneratedScroll() const; + void setIsClientGeneratedScroll(bool); + + bool isScrollNotificationSuppressed() const; + void setIsScrollNotificationSuppressed(bool); + + /* Called from within WebKit via ChromeClientBlackBerry */ + void checkOriginOfCurrentScrollOperation(); + +private: + BackingStoreClient(WebCore::Frame*, WebCore::Frame* parentFrame, WebPage* parentPage); + + WebCore::Frame* m_frame; + WebPage* m_webPage; + BackingStore* m_backingStore; + BackingStoreClient* m_parent; + bool m_isClientGeneratedScroll; + bool m_isScrollNotificationSuppressed; +}; + +} +} + +#endif // BackingStoreClient_h diff --git a/Source/WebKit/blackberry/WebKitSupport/BackingStoreCompositingSurface.cpp b/Source/WebKit/blackberry/WebKitSupport/BackingStoreCompositingSurface.cpp new file mode 100644 index 000000000..43e075a39 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/BackingStoreCompositingSurface.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "BackingStoreCompositingSurface.h" + +#include "GraphicsContext.h" +#include "SurfacePool.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include <BlackBerryPlatformGraphics.h> + +namespace BlackBerry { +namespace WebKit { + +CompositingSurfaceBuffer::CompositingSurfaceBuffer(const Platform::IntSize& size) + : m_size(size) + , m_buffer(0) +{ +} + +CompositingSurfaceBuffer::~CompositingSurfaceBuffer() +{ + destroyBuffer(m_buffer); +} + +Platform::IntSize CompositingSurfaceBuffer::surfaceSize() const +{ + return m_size; +} + +Platform::Graphics::Buffer* CompositingSurfaceBuffer::nativeBuffer() const +{ + if (!m_buffer) { + m_buffer = createBuffer(m_size, + Platform::Graphics::TileBuffer, + Platform::Graphics::GLES2); + } + return m_buffer; +} + +BackingStoreCompositingSurface::BackingStoreCompositingSurface(const Platform::IntSize& size, bool doubleBuffered) + : m_isDoubleBuffered(doubleBuffered) + , m_needsSync(true) +{ + m_frontBuffer = new CompositingSurfaceBuffer(size); + m_backBuffer = !doubleBuffered ? 0 : new CompositingSurfaceBuffer(size); +} + +BackingStoreCompositingSurface::~BackingStoreCompositingSurface() +{ + delete m_frontBuffer; + m_frontBuffer = 0; + + delete m_backBuffer; + m_backBuffer = 0; +} + +CompositingSurfaceBuffer* BackingStoreCompositingSurface::frontBuffer() const +{ + ASSERT(m_frontBuffer); + return m_frontBuffer; +} + +CompositingSurfaceBuffer* BackingStoreCompositingSurface::backBuffer() const +{ + if (!m_isDoubleBuffered) + return frontBuffer(); + + ASSERT(m_backBuffer); + return m_backBuffer; +} + +void BackingStoreCompositingSurface::swapBuffers() +{ + if (!m_isDoubleBuffered) + return; + + // Store temps. + unsigned front = reinterpret_cast<unsigned>(frontBuffer()); + unsigned back = reinterpret_cast<unsigned>(backBuffer()); + + // Atomic change. + _smp_xchg(reinterpret_cast<unsigned*>(&m_frontBuffer), back); + _smp_xchg(reinterpret_cast<unsigned*>(&m_backBuffer), front); +} + +} // namespace WebKit +} // namespace BlackBerry +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebKit/blackberry/WebKitSupport/BackingStoreCompositingSurface.h b/Source/WebKit/blackberry/WebKitSupport/BackingStoreCompositingSurface.h new file mode 100644 index 000000000..d4ec45c52 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/BackingStoreCompositingSurface.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BackingStoreCompositingSurface_h +#define BackingStoreCompositingSurface_h + +#if USE(ACCELERATED_COMPOSITING) + +#include <BlackBerryPlatformIntRectRegion.h> +#include <wtf/RefPtr.h> +#include <wtf/ThreadSafeRefCounted.h> + +namespace BlackBerry { + +namespace Platform { +namespace Graphics { +struct Buffer; +} +} + +namespace WebKit { +class CompositingSurfaceBuffer { +public: + CompositingSurfaceBuffer(const Platform::IntSize&); + ~CompositingSurfaceBuffer(); + Platform::IntSize surfaceSize() const; + + Platform::Graphics::Buffer* nativeBuffer() const; + +private: + Platform::IntSize m_size; + mutable Platform::Graphics::Buffer* m_buffer; +}; + + +class BackingStoreCompositingSurface : public ThreadSafeRefCounted<BackingStoreCompositingSurface> { +public: + static PassRefPtr<BackingStoreCompositingSurface> create(const Platform::IntSize& size, bool doubleBuffered) + { + return adoptRef(new BackingStoreCompositingSurface(size, doubleBuffered)); + } + + ~BackingStoreCompositingSurface(); + + CompositingSurfaceBuffer* frontBuffer() const; + CompositingSurfaceBuffer* backBuffer() const; + bool isDoubleBuffered() const { return m_isDoubleBuffered; } + void swapBuffers(); + + bool needsSync() const { return m_needsSync; } + void setNeedsSync(bool needsSync) { m_needsSync = needsSync; } + +private: + BackingStoreCompositingSurface(const Platform::IntSize&, bool doubleBuffered); + + mutable CompositingSurfaceBuffer* m_frontBuffer; + mutable CompositingSurfaceBuffer* m_backBuffer; + bool m_isDoubleBuffered; + bool m_needsSync; +}; + +} // namespace WebKit +} // namespace BlackBerry + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // BackingStoreCompositingSurface_h diff --git a/Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.cpp b/Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.cpp new file mode 100644 index 000000000..a02f93a1c --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "BackingStoreTile.h" + +#include "GraphicsContext.h" +#include "SurfacePool.h" + +#include <BlackBerryPlatformGraphics.h> + +namespace BlackBerry { +namespace WebKit { + +TileBuffer::TileBuffer(const Platform::IntSize& size) + : m_size(size) + , m_buffer(0) + , m_blitGeneration(0) +{ +} + +TileBuffer::~TileBuffer() +{ + destroyBuffer(m_buffer); +} + +Platform::IntSize TileBuffer::size() const +{ + return m_size; +} + +Platform::IntRect TileBuffer::rect() const +{ + return Platform::IntRect(Platform::IntPoint::zero(), m_size); +} + +bool TileBuffer::isRendered() const +{ + return isRendered(rect()); +} + +bool TileBuffer::isRendered(const Platform::IntRectRegion& contents) const +{ + return Platform::IntRectRegion::subtractRegions(contents, m_renderedRegion).isEmpty(); +} + +void TileBuffer::clearRenderedRegion(const Platform::IntRectRegion& region) +{ + m_renderedRegion = Platform::IntRectRegion::subtractRegions(m_renderedRegion, region); +} + +void TileBuffer::clearRenderedRegion() +{ + m_renderedRegion = Platform::IntRectRegion(); +} + +void TileBuffer::addRenderedRegion(const Platform::IntRectRegion& region) +{ + m_renderedRegion = Platform::IntRectRegion::unionRegions(region, m_renderedRegion); +} + +Platform::IntRectRegion TileBuffer::renderedRegion() const +{ + return m_renderedRegion; +} + +Platform::IntRectRegion TileBuffer::notRenderedRegion() const +{ + return Platform::IntRectRegion::subtractRegions(rect(), renderedRegion()); +} + +Platform::Graphics::Buffer* TileBuffer::nativeBuffer() const +{ + if (!m_buffer) + m_buffer = createBuffer(m_size, Platform::Graphics::TileBuffer, SurfacePool::globalSurfacePool()->sharedPixmapGroup()); + + return m_buffer; +} + + +BackingStoreTile::BackingStoreTile(const Platform::IntSize& size, BufferingMode mode) + : m_bufferingMode(mode) + , m_committed(false) + , m_backgroundPainted(false) + , m_horizontalShift(0) + , m_verticalShift(0) +{ + m_frontBuffer = new TileBuffer(size); +} + +BackingStoreTile::~BackingStoreTile() +{ + delete m_frontBuffer; + m_frontBuffer = 0; +} + +Platform::IntSize BackingStoreTile::size() const +{ + return frontBuffer()->size(); +} + +Platform::IntRect BackingStoreTile::rect() const +{ + return frontBuffer()->rect(); +} + +TileBuffer* BackingStoreTile::frontBuffer() const +{ + ASSERT(m_frontBuffer); + return m_frontBuffer; +} + +TileBuffer* BackingStoreTile::backBuffer() const +{ + if (m_bufferingMode == SingleBuffered) + return frontBuffer(); + + return SurfacePool::globalSurfacePool()->backBuffer(); +} + +void BackingStoreTile::swapBuffers() +{ + if (m_bufferingMode == SingleBuffered) + return; + + // Store temps. + unsigned front = reinterpret_cast<unsigned>(frontBuffer()); + unsigned back = reinterpret_cast<unsigned>(backBuffer()); + + // Atomic change. + _smp_xchg(reinterpret_cast<unsigned*>(&m_frontBuffer), back); + _smp_xchg(reinterpret_cast<unsigned*>(&SurfacePool::globalSurfacePool()->m_backBuffer), front); +} + +void BackingStoreTile::reset() +{ + setCommitted(false); + frontBuffer()->clearRenderedRegion(); + backBuffer()->clearRenderedRegion(); + clearShift(); +} + +void BackingStoreTile::paintBackground() +{ + m_backgroundPainted = true; + + clearBuffer(backBuffer()->nativeBuffer(), 0, 0, 0, 0); +} + +} +} diff --git a/Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.h b/Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.h new file mode 100644 index 000000000..7a0a42f5d --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BackingStoreTile_h +#define BackingStoreTile_h + +#include "BlackBerryPlatformIntRectRegion.h" +#include "BlackBerryPlatformPrimitives.h" + +namespace BlackBerry { +namespace Platform { +namespace Graphics { +struct Buffer; +} +} + +namespace WebKit { +class TileBuffer { + public: + TileBuffer(const Platform::IntSize&); + ~TileBuffer(); + Platform::IntSize size() const; + Platform::IntRect rect() const; + + bool isRendered() const; + bool isRendered(const Platform::IntRectRegion& contents) const; + void clearRenderedRegion(); + void clearRenderedRegion(const Platform::IntRectRegion&); + void addRenderedRegion(const Platform::IntRectRegion&); + Platform::IntRectRegion renderedRegion() const; + Platform::IntRectRegion notRenderedRegion() const; + + Platform::Graphics::Buffer* nativeBuffer() const; + + void setBlitGeneration(int g) const { m_blitGeneration = g; } + int blitGeneration() const { return m_blitGeneration; } + + private: + Platform::IntSize m_size; + Platform::IntRectRegion m_renderedRegion; + mutable Platform::Graphics::Buffer* m_buffer; + mutable int m_blitGeneration; +}; + + +class BackingStoreTile { +public: + enum BufferingMode { SingleBuffered, DoubleBuffered }; + + static BackingStoreTile* create(const Platform::IntSize& size, BufferingMode mode) + { + return new BackingStoreTile(size, mode); + } + + ~BackingStoreTile(); + + Platform::IntSize size() const; + Platform::IntRect rect() const; + + TileBuffer* frontBuffer() const; + TileBuffer* backBuffer() const; + bool isDoubleBuffered() const { return m_bufferingMode == DoubleBuffered; } + + void reset(); + bool backgroundPainted() const { return m_backgroundPainted; } + void paintBackground(); + + bool isCommitted() const { return m_committed; } + void setCommitted(bool committed) { m_committed = committed; } + + void clearShift() { m_horizontalShift = 0; m_verticalShift = 0; } + int horizontalShift() const { return m_horizontalShift; } + void setHorizontalShift(int shift) { m_horizontalShift = shift; } + int verticalShift() const { return m_verticalShift; } + void setVerticalShift(int shift) { m_verticalShift = shift; } + + void swapBuffers(); + +private: + BackingStoreTile(const Platform::IntSize&, BufferingMode); + + mutable TileBuffer* m_frontBuffer; + BufferingMode m_bufferingMode; + bool m_checkered; + bool m_committed; + bool m_backgroundPainted; + int m_horizontalShift; + int m_verticalShift; +}; + +} // namespace WebKit +} // namespace BlackBerry + +#endif // BackingStoreTile_h diff --git a/Source/WebKit/blackberry/WebKitSupport/DOMSupport.cpp b/Source/WebKit/blackberry/WebKitSupport/DOMSupport.cpp new file mode 100644 index 000000000..9dd5d2117 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/DOMSupport.cpp @@ -0,0 +1,404 @@ +/* + * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "DOMSupport.h" + +#include "FloatQuad.h" +#include "Frame.h" +#include "FrameView.h" +#include "HTMLFormElement.h" +#include "HTMLInputElement.h" +#include "HTMLNames.h" +#include "HTMLTextAreaElement.h" +#include "Node.h" +#include "Range.h" +#include "RenderObject.h" +#include "RenderText.h" +#include "RenderTextControl.h" +#include "TextIterator.h" +#include "VisibleSelection.h" +#include "WTFString.h" + +#include "htmlediting.h" +#include "visible_units.h" + +#include <limits> + +using WTF::Vector; + +using namespace WebCore; + +namespace BlackBerry { +namespace WebKit { +namespace DOMSupport { + +void visibleTextQuads(const Range& range, Vector<FloatQuad>& quads, bool useSelectionHeight) +{ + // Range::textQuads includes hidden text, which we don't want. + // To work around this, this is a copy of it which skips hidden elements. + Node* startContainer = range.startContainer(); + Node* endContainer = range.endContainer(); + + if (!startContainer || !endContainer) + return; + + Node* stopNode = range.pastLastNode(); + for (Node* node = range.firstNode(); node != stopNode; node = node->traverseNextNode()) { + RenderObject* r = node->renderer(); + if (!r || !r->isText()) + continue; + + if (r->style()->visibility() != VISIBLE) + continue; + + RenderText* renderText = toRenderText(r); + int startOffset = node == startContainer ? range.startOffset() : 0; + int endOffset = node == endContainer ? range.endOffset() : std::numeric_limits<int>::max(); + renderText->absoluteQuadsForRange(quads, startOffset, endOffset, useSelectionHeight); + } +} + +bool isTextInputElement(Element* element) +{ + return element->isTextFormControl() + || element->hasTagName(HTMLNames::textareaTag) + || element->isContentEditable(); +} + +bool isPasswordElement(const Element* element) +{ + return element && element->hasTagName(HTMLNames::inputTag) + && static_cast<const HTMLInputElement*>(element)->isPasswordField(); +} + +WTF::String inputElementText(Element* element) +{ + if (!element) + return WTF::String(); + + WTF::String elementText; + if (element->hasTagName(HTMLNames::inputTag)) { + const HTMLInputElement* inputElement = static_cast<const HTMLInputElement*>(element); + elementText = inputElement->value(); + } else if (element->hasTagName(HTMLNames::textareaTag)) { + const HTMLTextAreaElement* inputElement = static_cast<const HTMLTextAreaElement*>(element); + elementText = inputElement->value(); + } else if (element->isContentEditable()) { + RefPtr<Range> rangeForNode = rangeOfContents(element); + elementText = rangeForNode.get()->text(); + } + return elementText; +} + +bool isElementTypePlugin(const Element* element) +{ + if (!element) + return false; + + if (element->hasTagName(HTMLNames::objectTag) + || element->hasTagName(HTMLNames::embedTag) + || element->hasTagName(HTMLNames::appletTag)) + return true; + + return false; +} + +HTMLTextFormControlElement* toTextControlElement(Node* node) +{ + if (!(node && node->isElementNode())) + return 0; + + Element* element = static_cast<Element*>(node); + if (!element->isFormControlElement()) + return 0; + + HTMLFormControlElement* formElement = static_cast<HTMLFormControlElement*>(element); + if (!formElement->isTextFormControl()) + return 0; + + return static_cast<HTMLTextFormControlElement*>(formElement); +} + +bool isPopupInputField(const Element* element) +{ + return isDateTimeInputField(element) || isColorInputField(element); +} + +bool isDateTimeInputField(const Element* element) +{ + if (!element->hasTagName(HTMLNames::inputTag)) + return false; + + const HTMLInputElement* inputElement = static_cast<const HTMLInputElement*>(element); + + // The following types have popup's. + if (inputElement->isDateControl() + || inputElement->isDateTimeControl() + || inputElement->isDateTimeLocalControl() + || inputElement->isTimeControl() + || inputElement->isMonthControl()) + return true; + + return false; +} + +bool isColorInputField(const Element* element) +{ + if (!element->hasTagName(HTMLNames::inputTag)) + return false; + + const HTMLInputElement* inputElement = static_cast<const HTMLInputElement*>(element); + +#if ENABLE(INPUT_COLOR) + if (inputElement->isColorControl()) + return true; +#endif + + return false; +} + +AttributeState elementSupportsAutocorrect(const Element* element) +{ + // First we check the input item itself. If the attribute is not defined, + // we check its parent form. + QualifiedName autocorrectAttr = QualifiedName(nullAtom, "autocorrect", nullAtom); + if (element->fastHasAttribute(autocorrectAttr)) { + AtomicString attributeString = element->fastGetAttribute(autocorrectAttr); + if (equalIgnoringCase(attributeString, "off")) + return Off; + if (equalIgnoringCase(attributeString, "on")) + return On; + // If we haven't returned, it wasn't set properly. Check the form for an explicit setting + // because the attribute was provided, but invalid. + } + if (element->isFormControlElement()) { + const HTMLFormControlElement* formElement = static_cast<const HTMLFormControlElement*>(element); + if (formElement->form() && formElement->form()->fastHasAttribute(autocorrectAttr)) { + AtomicString attributeString = formElement->form()->fastGetAttribute(autocorrectAttr); + if (equalIgnoringCase(attributeString, "off")) + return Off; + if (equalIgnoringCase(attributeString, "on")) + return On; + } + } + + return Default; +} + +// Check if this is an input field that will be focused & require input support. +bool isTextBasedContentEditableElement(Element* element) +{ + if (!element) + return false; + + if (element->isReadOnlyFormControl()) + return false; + + if (isPopupInputField(element)) + return false; + + return element->isTextFormControl() || element->isContentEditable(); +} + +IntRect transformedBoundingBoxForRange(const Range& range) +{ + // Based on Range::boundingBox, which does not handle transforms, and + // RenderObject::absoluteBoundingBoxRect, which does. + IntRect result; + Vector<FloatQuad> quads; + visibleTextQuads(range, quads); + const size_t n = quads.size(); + for (size_t i = 0; i < n; ++i) + result.unite(quads[i].enclosingBoundingBox()); + + return result; +} + +VisibleSelection visibleSelectionForInputElement(Element* element) +{ + return visibleSelectionForRangeInputElement(element, 0, inputElementText(element).length()); +} + +VisibleSelection visibleSelectionForRangeInputElement(Element* element, int start, int end) +{ + if (DOMSupport::toTextControlElement(element)) { + RenderTextControl* textRender = toRenderTextControl(element->renderer()); + if (!textRender) + return VisibleSelection(); + + VisiblePosition startPosition = textRender->visiblePositionForIndex(start); + VisiblePosition endPosition; + if (start == end) + endPosition = startPosition; + else + endPosition = textRender->visiblePositionForIndex(end); + + return VisibleSelection(startPosition, endPosition); + } + + // Must be content editable, generate the range. + RefPtr<Range> selectionRange = TextIterator::rangeFromLocationAndLength(element, start, end - start); + if (start == end) + return VisibleSelection(selectionRange.get()->startPosition(), DOWNSTREAM); + + VisiblePosition visibleStart(selectionRange->startPosition(), DOWNSTREAM); + VisiblePosition visibleEnd(selectionRange->endPosition(), SEL_DEFAULT_AFFINITY); + + return VisibleSelection(visibleStart, visibleEnd); +} + +Node* DOMContainerNodeForPosition(const Position& position) +{ + Node* nodeAtPos = position.containerNode(); + if (nodeAtPos->isInShadowTree()) + nodeAtPos = nodeAtPos->shadowAncestorNode(); + + return nodeAtPos; +} + +bool isPositionInNode(Node* node, const Position& position) +{ + int offset = 0; + Node* domNodeAtPos = DOMContainerNodeForPosition(position); + if (domNodeAtPos == position.containerNode()) + offset = position.computeOffsetInContainerNode(); + + RefPtr<Range> rangeForNode = rangeOfContents(node); + int ec; + + return rangeForNode->isPointInRange(domNodeAtPos, offset, ec); +} + +// This is a Tristate return to allow us to override name matching when +// autocomplete is expressly requested for a field. Default indicates +// that the setting is On which is the default but not expressly requested +// for the element being checked. On indicates that it is directly added +// to the element. +AttributeState elementSupportsAutocomplete(const Element* element) +{ + if (!element->hasTagName(HTMLNames::inputTag)) + return Default; + + const HTMLInputElement* inputElement = static_cast<const HTMLInputElement*>(element); + if (inputElement->fastHasAttribute(HTMLNames::autocompleteAttr)) { + if (equalIgnoringCase(inputElement->fastGetAttribute(HTMLNames::autocompleteAttr), "on")) + return On; + } + + return inputElement->shouldAutocomplete() ? Default : Off; +} + +bool matchesReservedStringPreventingAutocomplete(AtomicString& string) +{ + if (string.contains("email", false /* caseSensitive */) + || string.contains("user", false /* caseSensitive */) + || string.contains("name", false /* caseSensitive */) + || string.contains("login", false /* caseSensitive */)) + return true; + + return false; +} + +// This checks to see if an input element has a name or id attribute set to +// username or email. These are rough checks to avoid major sites that use +// login fields as input type=text and auto correction interfers with. +bool elementIdOrNameIndicatesNoAutocomplete(const Element* element) +{ + if (!element->hasTagName(HTMLNames::inputTag)) + return false; + + AtomicString idAttribute = element->getIdAttribute(); + if (matchesReservedStringPreventingAutocomplete(idAttribute)) + return true; + + if (element->fastHasAttribute(HTMLNames::nameAttr)) { + AtomicString nameAttribute = element->fastGetAttribute(HTMLNames::nameAttr); + if (matchesReservedStringPreventingAutocomplete(nameAttribute)) + return true; + } + + return false; +} + +IntPoint convertPointToFrame(const Frame* sourceFrame, const Frame* targetFrame, const IntPoint& point) +{ + ASSERT(sourceFrame && targetFrame); + if (sourceFrame == targetFrame) + return point; + + ASSERT(sourceFrame->view() && targetFrame->view()); + ASSERT(targetFrame->tree()); + + Frame* targetFrameParent = targetFrame->tree()->parent(); + IntRect targetFrameRect = targetFrame->view()->frameRect(); + + // Convert the target frame rect to source window content coordinates. This is only required + // if the parent frame is not the source. If the parent is the source, subframeRect + // is already in source content coordinates. + if (targetFrameParent != sourceFrame) + targetFrameRect = sourceFrame->view()->windowToContents(targetFrameParent->view()->contentsToWindow(targetFrameRect)); + + // Requested point is outside of target frame, return InvalidPoint. + if (!targetFrameRect.contains(point)) + return InvalidPoint; + + // Adjust the points to be relative to the target. + return targetFrame->view()->windowToContents(sourceFrame->view()->contentsToWindow(point)); +} + +VisibleSelection visibleSelectionForClosestActualWordStart(const VisibleSelection& selection) +{ + // VisibleSelection validation has a special case when the caret is at the end of a paragraph where + // it selects the paragraph marker. As well, if the position is at the end of a word, it will select + // only the space between words. We want to select an actual word so we move the selection to + // the start of the leftmost word if the character after the selection point is whitespace. + if (selection.selectionType() != VisibleSelection::RangeSelection && isWhitespace(selection.visibleStart().characterAfter())) { + VisibleSelection leftSelection(previousWordPosition(selection.start())); + bool leftSelectionIsOnWord = !isWhitespace(leftSelection.visibleStart().characterAfter()); + + VisibleSelection rangeSelection(endOfWord(leftSelection.start()), selection.visibleStart()); + int leftDistance = TextIterator::rangeLength(rangeSelection.toNormalizedRange().get()); + + VisibleSelection rightSelection(nextWordPosition(selection.start())); + rightSelection = previousWordPosition(rightSelection.start()); + bool rightSelectionIsOnWord = !isWhitespace(rightSelection.visibleStart().characterAfter()); + + rangeSelection = VisibleSelection(rightSelection.visibleStart(), selection.visibleStart()); + int rightDistance = TextIterator::rangeLength(rangeSelection.toNormalizedRange().get()); + + // Make sure we found an actual word. If not, return the original selection. + if (!leftSelectionIsOnWord && !rightSelectionIsOnWord) + return selection; + + if (!rightSelectionIsOnWord || (leftSelectionIsOnWord && leftDistance < rightDistance)) { + // Left is closer or right is invalid. + return leftSelection; + } + + // Right is closer or equal, or left was invalid. + return rightSelection; + } + + // No adjustment required. + return selection; +} + +} // DOMSupport +} // WebKit +} // BlackBerry diff --git a/Source/WebKit/blackberry/WebKitSupport/DOMSupport.h b/Source/WebKit/blackberry/WebKitSupport/DOMSupport.h new file mode 100644 index 000000000..1e0945189 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/DOMSupport.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DOMSupport_h +#define DOMSupport_h + +#include "IntPoint.h" +#include "IntRect.h" + +#include <wtf/Vector.h> + +namespace WTF { +class String; +} + +namespace WebCore { +class Element; +class FloatQuad; +class Frame; +class HTMLTextFormControlElement; +class Node; +class Position; +class Range; +class VisibleSelection; +} + +namespace BlackBerry { +namespace WebKit { +namespace DOMSupport { + +enum AttributeState { On, Off, Default }; + +bool isElementTypePlugin(const WebCore::Element*); + +bool isTextInputElement(WebCore::Element*); +bool isTextBasedContentEditableElement(WebCore::Element*); +bool isPasswordElement(const WebCore::Element*); + +bool isPopupInputField(const WebCore::Element*); +bool isDateTimeInputField(const WebCore::Element*); +bool isColorInputField(const WebCore::Element*); +AttributeState elementSupportsAutocorrect(const WebCore::Element*); + +WTF::String inputElementText(WebCore::Element*); + +WebCore::HTMLTextFormControlElement* toTextControlElement(WebCore::Node*); + +WebCore::IntRect transformedBoundingBoxForRange(const WebCore::Range&); +void visibleTextQuads(const WebCore::Range&, WTF::Vector<WebCore::FloatQuad>& quads, bool useSelectionHeight = false); + +WebCore::VisibleSelection visibleSelectionForRangeInputElement(WebCore::Element*, int start, int end); +WebCore::VisibleSelection visibleSelectionForInputElement(WebCore::Element*); + +WebCore::Node* DOMContainerNodeForPosition(const WebCore::Position&); +bool isPositionInNode(WebCore::Node*, const WebCore::Position&); + +AttributeState elementSupportsAutocomplete(const WebCore::Element*); +bool elementIdOrNameIndicatesNoAutocomplete(const WebCore::Element*); + +WebCore::IntPoint convertPointToFrame(const WebCore::Frame* sourceFrame, const WebCore::Frame* targetFrame, const WebCore::IntPoint& sourcePoint); + +static const WebCore::IntPoint InvalidPoint = WebCore::IntPoint(-1, -1); + +WebCore::VisibleSelection visibleSelectionForClosestActualWordStart(const WebCore::VisibleSelection&); + +} // DOMSupport +} // WebKit +} // BlackBerry + +#endif // DOMSupport_h diff --git a/Source/WebKit/blackberry/WebKitSupport/FatFingers.cpp b/Source/WebKit/blackberry/WebKitSupport/FatFingers.cpp new file mode 100644 index 000000000..016a42620 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/FatFingers.cpp @@ -0,0 +1,537 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "FatFingers.h" + +#include "BlackBerryPlatformLog.h" +#include "BlackBerryPlatformScreen.h" +#include "BlackBerryPlatformSettings.h" +#include "CSSComputedStyleDeclaration.h" +#include "CSSParser.h" +#include "DOMSupport.h" +#include "Document.h" +#include "Element.h" +#include "EventNames.h" +#include "ExceptionCode.h" +#include "FloatQuad.h" +#include "Frame.h" +#include "FrameView.h" +#include "HTMLFrameOwnerElement.h" +#include "HTMLInputElement.h" +#include "HTMLNames.h" +#include "HTMLTextAreaElement.h" +#include "Range.h" +#include "RenderObject.h" +#include "RenderView.h" +#include "Text.h" +#include "TextBreakIterator.h" +#include "WebPage_p.h" + +#if DEBUG_FAT_FINGERS +#include "BackingStore.h" +#endif + +using BlackBerry::Platform::LogLevelInfo; +using BlackBerry::Platform::log; +using BlackBerry::Platform::IntRectRegion; +using WTF::RefPtr; + +using namespace WebCore; + +// Lets make the top padding bigger than other directions, since it gets us more +// accurate clicking results. + +namespace BlackBerry { +namespace WebKit { + +#if DEBUG_FAT_FINGERS +IntRect FatFingers::m_debugFatFingerRect; +IntPoint FatFingers::m_debugFatFingerClickPosition; +IntPoint FatFingers::m_debugFatFingerAdjustedPosition; +#endif + +IntRect FatFingers::fingerRectForPoint(const IntPoint& point) const +{ + unsigned topPadding, rightPadding, bottomPadding, leftPadding; + getPaddings(topPadding, rightPadding, bottomPadding, leftPadding); + + return HitTestResult::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding); +} + +static bool hasMousePressListener(Element* element) +{ + ASSERT(element); + return element->hasEventListeners(eventNames().clickEvent) + || element->hasEventListeners(eventNames().mousedownEvent) + || element->hasEventListeners(eventNames().mouseupEvent); +} + +bool FatFingers::isElementClickable(Element* element) const +{ + ASSERT(element); + ASSERT(m_matchingApproach != Done); + ASSERT(m_targetType == ClickableElement); + + switch (m_matchingApproach) { + case ClickableByDefault: { + ExceptionCode ec = 0; + return element->webkitMatchesSelector("a[href],*:link,*:visited,*[role=button],button,input,select,label[for],area[href],textarea,embed,object", ec) + || element->isMediaControlElement() + || element->isContentEditable(); + } + case MadeClickableByTheWebpage: + + // Elements within a shadow DOM can not be 'made clickable by the webpage', since + // they are not accessible. + if (element->isInShadowTree()) + return false; + + // FIXME: We fall back to checking for the presence of CSS style "cursor: pointer" to indicate whether the element A + // can be clicked when A neither registers mouse events handlers nor is a hyperlink or form control. This workaround + // ensures that we don't break various Google web apps, including <http://maps.google.com>. Ideally, we should walk + // up the DOM hierarchy to determine the first parent element that accepts mouse events. + // Consider the HTML snippet: <div id="A" onclick="..."><div id="B">Example</div></div> + // Notice, B is not a hyperlink, or form control, and does not register any mouse event handler. Then B cannot + // be clicked. Suppose B specified the CSS property "cursor: pointer". Then, B will be considered as clickable. + return hasMousePressListener(element) + || computedStyle(element)->getPropertyValue(cssPropertyID("cursor")) == "pointer"; + default: + ASSERT_NOT_REACHED(); + } + + return false; +} + +// FIXME: Handle content editable nodes here too. +static inline bool isFieldWithText(Node* node) +{ + ASSERT(node); + if (!node || !node->isElementNode()) + return false; + + Element* element = toElement(node); + return !DOMSupport::inputElementText(element).isEmpty(); +} + +static inline int distanceBetweenPoints(const IntPoint& p1, const IntPoint& p2) +{ + int dx = p1.x() - p2.x(); + int dy = p1.y() - p2.y(); + return sqrt((double)((dx * dx) + (dy * dy))); +} + +static bool compareDistanceBetweenPoints(const Platform::IntPoint& p, const Platform::IntRectRegion& r1, const Platform::IntRectRegion& r2) +{ + return distanceBetweenPoints(p, r1.extents().center()) > distanceBetweenPoints(p, r2.extents().center()); +} + +static bool isValidFrameOwner(WebCore::Element* element) +{ + ASSERT(element); + return element->isFrameOwnerElement() && static_cast<HTMLFrameOwnerElement*>(element)->contentFrame(); +} + +// NOTE: 'contentPos' is in main frame contents coordinates. +FatFingers::FatFingers(WebPagePrivate* webPage, const WebCore::IntPoint& contentPos, TargetType targetType) + : m_webPage(webPage) + , m_contentPos(contentPos) + , m_targetType(targetType) + , m_matchingApproach(Done) +{ + ASSERT(webPage); + +#if DEBUG_FAT_FINGERS + m_debugFatFingerRect = IntRect(0, 0, 0, 0); + m_debugFatFingerClickPosition = m_webPage->mapToTransformed(m_webPage->mapFromContentsToViewport(contentPos)); + m_debugFatFingerAdjustedPosition = m_webPage->mapToTransformed(m_webPage->mapFromContentsToViewport(contentPos)); +#endif +} + +FatFingers::~FatFingers() +{ +} + +const FatFingersResult FatFingers::findBestPoint() +{ + ASSERT(m_webPage); + ASSERT(m_webPage->m_mainFrame); + + m_cachedRectHitTestResults.clear(); + + FatFingersResult result(m_contentPos); + m_matchingApproach = ClickableByDefault; + + // Lets set nodeUnderFatFinger to the result of a point based hit test here. If something + // targable is actually found by ::findIntersectingRegions, then we might replace what we just set below later on. + Element* elementUnderPoint; + Element* clickableElementUnderPoint; + getRelevantInfoFromPoint(m_webPage->m_mainFrame->document(), m_contentPos, elementUnderPoint, clickableElementUnderPoint); + + if (elementUnderPoint) { + result.m_nodeUnderFatFinger = elementUnderPoint; + + // If we are looking for a Clickable Element and we found one, we can quit early. + if (m_targetType == ClickableElement) { + if (clickableElementUnderPoint) { + setSuccessfulFatFingersResult(result, clickableElementUnderPoint, m_contentPos /*adjustedPosition*/); + return result; + } + + if (isElementClickable(elementUnderPoint)) { + setSuccessfulFatFingersResult(result, elementUnderPoint, m_contentPos /*adjustedPosition*/); + return result; + } + } + } + +#if DEBUG_FAT_FINGERS + // Force blit to make the fat fingers rects show up. + if (!m_debugFatFingerRect.isEmpty()) + m_webPage->m_backingStore->repaint(0, 0, m_webPage->transformedViewportSize().width(), m_webPage->transformedViewportSize().height(), true, true); +#endif + + Vector<IntersectingRegion> intersectingRegions; + Platform::IntRectRegion remainingFingerRegion = Platform::IntRectRegion(fingerRectForPoint(m_contentPos)); + + bool foundOne = findIntersectingRegions(m_webPage->m_mainFrame->document(), intersectingRegions, remainingFingerRegion); + if (!foundOne) { + m_matchingApproach = MadeClickableByTheWebpage; + remainingFingerRegion = Platform::IntRectRegion(fingerRectForPoint(m_contentPos)); + foundOne = findIntersectingRegions(m_webPage->m_mainFrame->document(), intersectingRegions, remainingFingerRegion); + } + + m_matchingApproach = Done; + m_cachedRectHitTestResults.clear(); + + if (!foundOne) + return result; + + Node* bestNode = 0; + Platform::IntRectRegion largestIntersectionRegion; + IntPoint bestPoint; + int largestIntersectionRegionArea = 0; + + Vector<IntersectingRegion>::const_iterator endIt = intersectingRegions.end(); + for (Vector<IntersectingRegion>::const_iterator it = intersectingRegions.begin(); it != endIt; ++it) { + Node* currentNode = it->first; + Platform::IntRectRegion currentIntersectionRegion = it->second; + + int currentIntersectionRegionArea = currentIntersectionRegion.area(); + if (currentIntersectionRegionArea > largestIntersectionRegionArea + || (currentIntersectionRegionArea == largestIntersectionRegionArea + && compareDistanceBetweenPoints(m_contentPos, currentIntersectionRegion, largestIntersectionRegion))) { + bestNode = currentNode; + largestIntersectionRegion = currentIntersectionRegion; + largestIntersectionRegionArea = currentIntersectionRegionArea; + } + } + + if (!bestNode || largestIntersectionRegion.isEmpty()) + return result; + +#if DEBUG_FAT_FINGERS + m_debugFatFingerAdjustedPosition = m_webPage->mapToTransformed(m_webPage->mapFromContentsToViewport(largestIntersectionRegion.rects()[0].center())); +#endif + + setSuccessfulFatFingersResult(result, bestNode, largestIntersectionRegion.rects()[0].center() /*adjustedPosition*/); + + return result; +} + +// 'region' is in contents coordinates relative to the frame containing 'node' +// 'remainingFingerRegion' and 'intersectingRegions' will always be in main frame contents +// coordinates. +// Thus, before comparing, we need to map the former to main frame contents coordinates. +bool FatFingers::checkFingerIntersection(const Platform::IntRectRegion& region, + const Platform::IntRectRegion& remainingFingerRegion, + Node* node, Vector<IntersectingRegion>& intersectingRegions) +{ + ASSERT(node); + + Platform::IntRectRegion regionCopy(region); + WebCore::IntPoint framePos(m_webPage->frameOffset(node->document()->frame())); + regionCopy.move(framePos.x(), framePos.y()); + + Platform::IntRectRegion intersection = intersectRegions(regionCopy, remainingFingerRegion); + if (intersection.isEmpty()) + return false; + +#if DEBUG_FAT_FINGERS + String nodeName; + if (node->isTextNode()) + nodeName = "text node"; + else if (node->isElementNode()) + nodeName = String::format("%s node", toElement(node)->tagName().latin1().data()); + else + nodeName = "unknown node"; + log(LogLevelInfo, "%s has region %s, intersecting at %s (area %d)", nodeName.latin1().data(), + regionCopy.toString().c_str(), intersection.toString().c_str(), intersection.area()); +#endif + + intersectingRegions.append(std::make_pair(node, intersection)); + return true; +} + + +// intersectingRegions and remainingFingerRegion are all in main frame contents coordinates, +// even on recursive calls of ::findIntersectingRegions. +bool FatFingers::findIntersectingRegions(Document* document, + Vector<IntersectingRegion>& intersectingRegions, Platform::IntRectRegion& remainingFingerRegion) +{ + if (!document || !document->frame()->view()) + return false; + + // The layout needs to be up-to-date to determine if a node is focusable. + document->updateLayoutIgnorePendingStylesheets(); + + // Create fingerRect. + IntPoint frameContentPos(document->frame()->view()->windowToContents(m_webPage->m_mainFrame->view()->contentsToWindow(m_contentPos))); + +#if DEBUG_FAT_FINGERS + IntRect fingerRect(fingerRectForPoint(frameContentPos)); + IntRect screenFingerRect = m_webPage->mapToTransformed(fingerRect); + log(LogLevelInfo, "fat finger rect now %s", screenFingerRect.toString().latin1().data()); + + // only record the first finger rect + if (document == m_webPage->m_mainFrame->document()) + m_debugFatFingerRect = m_webPage->mapToTransformed(m_webPage->mapFromContentsToViewport(fingerRect)); +#endif + + bool foundOne = false; + + RenderLayer* lowestPositionedEnclosingLayerSoFar = 0; + + // Iterate over the list of nodes (and subrects of nodes where possible), for each saving the + // intersection of the bounding box with the finger rect. + ListHashSet<RefPtr<Node> > intersectedNodes; + getNodesFromRect(document, frameContentPos, intersectedNodes); + + ListHashSet<RefPtr<Node> >::const_iterator it = intersectedNodes.begin(); + ListHashSet<RefPtr<Node> >::const_iterator end = intersectedNodes.end(); + for ( ; it != end; ++it) { + Node* curNode = (*it).get(); + if (!curNode || !curNode->renderer()) + continue; + + if (remainingFingerRegion.isEmpty()) + break; + + bool isElement = curNode->isElementNode(); + if (isElement && isValidFrameOwner(toElement(curNode))) { + + HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(curNode); + Document* childDocument = owner && owner->contentFrame() ? owner->contentFrame()->document() : 0; + if (!childDocument) + continue; + + ASSERT(childDocument->frame()->view()); + + foundOne |= findIntersectingRegions(childDocument, intersectingRegions, remainingFingerRegion); + } else if (isElement && m_targetType == ClickableElement) { + foundOne |= checkForClickableElement(toElement(curNode), intersectingRegions, remainingFingerRegion, lowestPositionedEnclosingLayerSoFar); + } else if (m_targetType == Text) + foundOne |= checkForText(curNode, intersectingRegions, remainingFingerRegion); + } + + return foundOne; +} + +bool FatFingers::checkForClickableElement(Element* curElement, + Vector<IntersectingRegion>& intersectingRegions, + Platform::IntRectRegion& remainingFingerRegion, + RenderLayer*& lowestPositionedEnclosingLayerSoFar) +{ + ASSERT(curElement); + + bool intersects = false; + Platform::IntRectRegion elementRegion; + + bool isClickableElement = isElementClickable(curElement); + if (isClickableElement) { + if (curElement->isLink()) { + // Links can wrap lines, and in such cases Node::getRect() can give us + // not accurate rects, since it unites all InlineBox's rects. In these + // cases, we can process each line of the link separately with our + // intersection rect, getting a more accurate clicking. + Vector<FloatQuad> quads; + curElement->renderer()->absoluteFocusRingQuads(quads); + + size_t n = quads.size(); + ASSERT(n); + + for (size_t i = 0; i < n; ++i) + elementRegion = unionRegions(elementRegion, Platform::IntRect(quads[i].enclosingBoundingBox())); + } else + elementRegion = Platform::IntRectRegion(curElement->renderer()->absoluteBoundingBoxRect(true /*use transforms*/)); + + } else + elementRegion = Platform::IntRectRegion(curElement->renderer()->absoluteBoundingBoxRect(true /*use transforms*/)); + + if (lowestPositionedEnclosingLayerSoFar) { + RenderLayer* curElementRenderLayer = m_webPage->enclosingPositionedAncestorOrSelfIfPositioned(curElement->renderer()->enclosingLayer()); + if (curElementRenderLayer != lowestPositionedEnclosingLayerSoFar) { + + // elementRegion will always be in contents coordinates of its container frame. It needs to be + // mapped to main frame contents coordinates in order to subtract the fingerRegion, then. + WebCore::IntPoint framePos(m_webPage->frameOffset(curElement->document()->frame())); + Platform::IntRectRegion layerRegion(Platform::IntRect(lowestPositionedEnclosingLayerSoFar->renderer()->absoluteBoundingBoxRect(true/*use transforms*/))); + layerRegion.move(framePos.x(), framePos.y()); + + remainingFingerRegion = subtractRegions(remainingFingerRegion, layerRegion); + + lowestPositionedEnclosingLayerSoFar = curElementRenderLayer; + } + } else + lowestPositionedEnclosingLayerSoFar = m_webPage->enclosingPositionedAncestorOrSelfIfPositioned(curElement->renderer()->enclosingLayer()); + + if (isClickableElement) + intersects = checkFingerIntersection(elementRegion, remainingFingerRegion, curElement, intersectingRegions); + + return intersects; +} + +bool FatFingers::checkForText(Node* curNode, Vector<IntersectingRegion>& intersectingRegions, Platform::IntRectRegion& fingerRegion) +{ + ASSERT(curNode); + if (isFieldWithText(curNode)) { + // FIXME: Find all text in the field and find the best word. + // For now, we will just select the whole field. + IntRect boundingRect = curNode->renderer()->absoluteBoundingBoxRect(true /*use transforms*/); + Platform::IntRectRegion nodeRegion(boundingRect); + return checkFingerIntersection(nodeRegion, fingerRegion, curNode, intersectingRegions); + } + + if (curNode->isTextNode()) { + WebCore::Text* curText = static_cast<WebCore::Text*>(curNode); + String allText = curText->wholeText(); + + // Iterate through all words, breaking at whitespace, to find the bounding box of each word. + TextBreakIterator* wordIterator = wordBreakIterator(allText.characters(), allText.length()); + + int lastOffset = textBreakFirst(wordIterator); + if (lastOffset == -1) + return false; + + bool foundOne = false; + int offset; + Document* document = curNode->document(); + + while ((offset = textBreakNext(wordIterator)) != -1) { + RefPtr<Range> range = Range::create(document, curText, lastOffset, curText, offset); + if (!range->text().stripWhiteSpace().isEmpty()) { +#if DEBUG_FAT_FINGERS + log(LogLevelInfo, "Checking word '%s'", range->text().latin1().data()); +#endif + Platform::IntRectRegion rangeRegion(DOMSupport::transformedBoundingBoxForRange(*range)); + foundOne |= checkFingerIntersection(rangeRegion, fingerRegion, curNode, intersectingRegions); + } + lastOffset = offset; + } + return foundOne; + } + return false; +} + +void FatFingers::getPaddings(unsigned& top, unsigned& right, unsigned& bottom, unsigned& left) const +{ + static unsigned topPadding = Platform::Settings::get()->topFatFingerPadding(); + static unsigned rightPadding = Platform::Settings::get()->rightFatFingerPadding(); + static unsigned bottomPadding = Platform::Settings::get()->bottomFatFingerPadding(); + static unsigned leftPadding = Platform::Settings::get()->leftFatFingerPadding(); + + double currentScale = m_webPage->currentScale(); + top = topPadding / currentScale; + right = rightPadding / currentScale; + bottom = bottomPadding / currentScale; + left = leftPadding / currentScale; +} + +FatFingers::CachedResultsStrategy FatFingers::cachingStrategy() const +{ + switch (m_matchingApproach) { + case ClickableElement: + return GetFromRenderTree; + case MadeClickableByTheWebpage: + return GetFromCache; + case Done: + default: + ASSERT_NOT_REACHED(); + return GetFromRenderTree; + } +} + +void FatFingers::getNodesFromRect(Document* document, const IntPoint& contentPos, ListHashSet<RefPtr<WebCore::Node> >& intersectedNodes) +{ + FatFingers::CachedResultsStrategy cacheResolvingStrategy = cachingStrategy(); + + if (cacheResolvingStrategy == GetFromCache) { + ASSERT(m_cachedRectHitTestResults.contains(document)); + intersectedNodes = m_cachedRectHitTestResults.get(document); + return; + } + + ASSERT(cacheResolvingStrategy == GetFromRenderTree); + + unsigned topPadding, rightPadding, bottomPadding, leftPadding; + getPaddings(topPadding, rightPadding, bottomPadding, leftPadding); + + HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping); + HitTestResult result(contentPos, topPadding, rightPadding, bottomPadding, leftPadding, HitTestShadowDOM); + + document->renderView()->layer()->hitTest(request, result); + intersectedNodes = result.rectBasedTestResult(); + m_cachedRectHitTestResults.add(document, intersectedNodes); +} + +void FatFingers::getRelevantInfoFromPoint(Document* document, const IntPoint& contentPos, Element*& elementUnderPoint, Element*& clickableElementUnderPoint) const +{ + elementUnderPoint = 0; + clickableElementUnderPoint = 0; + + if (!document || !document->renderer() || !document->frame()) + return; + + HitTestResult result = document->frame()->eventHandler()->hitTestResultAtPoint(contentPos, true /*allowShadowContent*/); + Node* node = result.innerNode(); + while (node && !node->isElementNode()) + node = node->parentNode(); + + elementUnderPoint = static_cast<Element*>(node); + clickableElementUnderPoint = result.URLElement(); +} + +void FatFingers::setSuccessfulFatFingersResult(FatFingersResult& result, Node* bestNode, const WebCore::IntPoint& adjustedPoint) +{ + result.m_nodeUnderFatFinger = bestNode; + result.m_adjustedPosition = adjustedPoint; + result.m_positionWasAdjusted = true; + result.m_isValid = true; + + bool isTextInputElement = false; + if (m_targetType == ClickableElement) { + ASSERT(bestNode->isElementNode()); + Element* bestElement = static_cast<Element*>(bestNode); + isTextInputElement = DOMSupport::isTextInputElement(bestElement); + } + result.m_isTextInput = isTextInputElement; +} + +} +} + diff --git a/Source/WebKit/blackberry/WebKitSupport/FatFingers.h b/Source/WebKit/blackberry/WebKitSupport/FatFingers.h new file mode 100644 index 000000000..cb31f977a --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/FatFingers.h @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FatFingers_h +#define FatFingers_h + +#include "HitTestResult.h" +#include "RenderLayer.h" + +#include <BlackBerryPlatformIntRectRegion.h> + +#include <utility> + +#include <wtf/HashSet.h> +#include <wtf/ListHashSet.h> +#include <wtf/Vector.h> + +namespace WebCore { +class Document; +class Element; +class IntPoint; +class IntRect; +class IntSize; +class Node; +} + +#define DEBUG_FAT_FINGERS 0 + +namespace BlackBerry { +namespace WebKit { + +class WebPagePrivate; +class FatFingers; +class TouchEventHandler; + +class FatFingersResult { +public: + + FatFingersResult(const WebCore::IntPoint& p = WebCore::IntPoint::zero()) + : m_originalPosition(p) + , m_adjustedPosition(p) + , m_positionWasAdjusted(false) + , m_isTextInput(false) + , m_isValid(false) + , m_nodeUnderFatFinger(0) + { + } + + void reset() + { + m_originalPosition = m_adjustedPosition = WebCore::IntPoint::zero(); + m_positionWasAdjusted = false; + m_isTextInput = false; + m_isValid = false; + m_nodeUnderFatFinger = 0; + } + + WebCore::IntPoint originPosition() const { return m_originalPosition; } + WebCore::IntPoint adjustedPosition() const { return m_adjustedPosition; } + bool positionWasAdjusted() const { return m_isValid && m_positionWasAdjusted; } + bool isTextInput() const { return m_isValid && !!m_nodeUnderFatFinger && m_isTextInput; } + bool isValid() const { return m_isValid; } + + enum ContentType { ShadowContentAllowed, ShadowContentNotAllowed }; + + WebCore::Node* node(ContentType type = ShadowContentAllowed) const + { + if (!m_nodeUnderFatFinger || !m_nodeUnderFatFinger->inDocument()) + return 0; + + WebCore::Node* result = m_nodeUnderFatFinger.get(); + + if (type == ShadowContentAllowed) + return result; + + // Shadow trees can be nested. + while (result->isInShadowTree()) + result = toElement(result->shadowAncestorNode()); + + return result; + } + + WebCore::Element* nodeAsElementIfApplicable(ContentType type = ShadowContentAllowed) const + { + WebCore::Node* result = node(type); + if (!result || !result->isElementNode()) + return 0; + + return static_cast<WebCore::Element*>(result); + } + +private: + friend class WebKit::FatFingers; + friend class WebKit::TouchEventHandler; + + WebCore::IntPoint m_originalPosition; // Main frame contents coordinates. + WebCore::IntPoint m_adjustedPosition; // Main frame contents coordinates. + bool m_positionWasAdjusted; + bool m_isTextInput; // Check if the element under the touch point will require a VKB be displayed so that + // the touch down can be suppressed. + bool m_isValid; + RefPtr<WebCore::Node> m_nodeUnderFatFinger; +}; + +class FatFingers { +public: + enum TargetType { ClickableElement, Text }; + + FatFingers(WebPagePrivate* webpage, const WebCore::IntPoint& contentPos, TargetType); + ~FatFingers(); + + const FatFingersResult findBestPoint(); + +#if DEBUG_FAT_FINGERS + // These debug vars are all in content coordinates. They are public so + // they can be read from BackingStore, which will draw a visible rect + // around the fat fingers area. + static WebCore::IntRect m_debugFatFingerRect; + static WebCore::IntPoint m_debugFatFingerClickPosition; + static WebCore::IntPoint m_debugFatFingerAdjustedPosition; +#endif + +private: + enum MatchingApproachForClickable { ClickableByDefault = 0, MadeClickableByTheWebpage, Done }; + + typedef std::pair<WebCore::Node*, Platform::IntRectRegion> IntersectingRegion; + + enum CachedResultsStrategy { GetFromRenderTree = 0, GetFromCache }; + CachedResultsStrategy cachingStrategy() const; + typedef HashMap<RefPtr<WebCore::Document>, ListHashSet<RefPtr<WebCore::Node> > > CachedRectHitTestResults; + + bool checkFingerIntersection(const Platform::IntRectRegion&, + const Platform::IntRectRegion& remainingFingerRegion, + WebCore::Node*, + Vector<IntersectingRegion>& intersectingRegions); + + bool findIntersectingRegions(WebCore::Document*, + Vector<IntersectingRegion>& intersectingRegions, + Platform::IntRectRegion& remainingFingerRegion); + + bool checkForClickableElement(WebCore::Element*, + Vector<IntersectingRegion>& intersectingRegions, + Platform::IntRectRegion& remainingFingerRegion, + WebCore::RenderLayer*& lowestPositionedEnclosingLayerSoFar); + + bool checkForText(WebCore::Node*, + Vector<IntersectingRegion>& intersectingRegions, + Platform::IntRectRegion& fingerRegion); + + void setSuccessfulFatFingersResult(FatFingersResult&, WebCore::Node*, const WebCore::IntPoint&); + + void getNodesFromRect(WebCore::Document*, const WebCore::IntPoint&, ListHashSet<RefPtr<WebCore::Node> >&); + + // It mimics Document::elementFromPoint, but recursively hit-tests in case an inner frame is found. + void getRelevantInfoFromPoint(WebCore::Document*, + const WebCore::IntPoint&, + WebCore::Element*& elementUnderPoint, + WebCore::Element*& clickableElementUnderPoint) const; + + bool isElementClickable(WebCore::Element*) const; + + inline WebCore::IntRect fingerRectForPoint(const WebCore::IntPoint&) const; + void getPaddings(unsigned& top, unsigned& right, unsigned& bottom, unsigned& left) const; + + WebPagePrivate* m_webPage; + WebCore::IntPoint m_contentPos; + TargetType m_targetType; + MatchingApproachForClickable m_matchingApproach; + CachedRectHitTestResults m_cachedRectHitTestResults; +}; + +} +} + +#endif // FatFingers_h + diff --git a/Source/WebKit/blackberry/WebKitSupport/GLES2Context.cpp b/Source/WebKit/blackberry/WebKitSupport/GLES2Context.cpp new file mode 100644 index 000000000..55b9e15dd --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/GLES2Context.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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 + * OWNER 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 "GLES2Context.h" + +#include "Assertions.h" +#include "BackingStoreCompositingSurface.h" +#include "Chrome.h" +#include "ChromeClient.h" +#include "SurfacePool.h" +#include "WebPageClient.h" +#include "WebPage_p.h" + +#include <GLES2/gl2.h> + +namespace BlackBerry { +namespace WebKit { + +BackingStoreCompositingSurface* GLES2Context::compositingSurface() const +{ + return SurfacePool::globalSurfacePool()->compositingSurface(); +} + +Platform::Graphics::Buffer* GLES2Context::buffer() const +{ + if (m_window) + return m_window->buffer(); + +#if ENABLE_COMPOSITING_SURFACE + if (BackingStoreCompositingSurface* surface = compositingSurface()) + return surface->backBuffer()->nativeBuffer(); +#endif + + ASSERT_NOT_REACHED(); + return 0; +} + +PassOwnPtr<GLES2Context> GLES2Context::create(WebPagePrivate* page) +{ + return adoptPtr(new GLES2Context(page)); +} + +GLES2Context::GLES2Context(WebPagePrivate* page) + : m_window(0) +{ + if (page->m_client->window()->windowUsage() == Platform::Graphics::Window::GLES2Usage) + m_window = page->m_client->window(); +} + +GLES2Context::~GLES2Context() +{ +} + +Platform::IntSize GLES2Context::surfaceSize() const +{ + if (m_window) + return m_window->surfaceSize(); + +#if ENABLE_COMPOSITING_SURFACE + if (BackingStoreCompositingSurface* surface = compositingSurface()) + return surface->backBuffer()->surfaceSize(); +#endif + + ASSERT_NOT_REACHED(); + return Platform::IntSize(); +} + +bool GLES2Context::makeCurrent() +{ + Platform::Graphics::makeBufferCurrent(buffer(), Platform::Graphics::GLES2); + return true; +} + +bool GLES2Context::swapBuffers() +{ + ASSERT(glGetError() == GL_NO_ERROR); + +#if ENABLE_COMPOSITING_SURFACE + // Because we are rendering compositing contents into an off-screen pixmap and + // we need to blend the pixmap with the web page window surface we have to call + // glFinish() here. + glFinish(); + + if (BackingStoreCompositingSurface* surface = compositingSurface()) + surface->swapBuffers(); +#endif + + return true; +} + +} // namespace WebKit +} // namespace BlackBerry diff --git a/Source/WebKit/chromium/src/BoundObject.cpp b/Source/WebKit/blackberry/WebKitSupport/GLES2Context.h index d0f66aac5..ce7e84694 100644 --- a/Source/WebKit/chromium/src/BoundObject.cpp +++ b/Source/WebKit/blackberry/WebKitSupport/GLES2Context.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,53 +29,38 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "BoundObject.h" +#ifndef GLES2Context_h +#define GLES2Context_h -#include "V8Binding.h" -#include "V8Proxy.h" +#include <BlackBerryPlatformGLES2Context.h> +#include <BlackBerryPlatformWindow.h> +#include <wtf/Noncopyable.h> +#include <wtf/PassOwnPtr.h> +namespace BlackBerry { namespace WebKit { -BoundObject::BoundObject(v8::Handle<v8::Context> context, void* v8This, const char* objectName) - : m_objectName(objectName) - , m_context(context) - , m_v8This(v8This) -{ - v8::Context::Scope contextScope(context); - v8::Local<v8::FunctionTemplate> localTemplate = v8::FunctionTemplate::New(WebCore::V8Proxy::checkNewLegal); - m_hostTemplate = v8::Persistent<v8::FunctionTemplate>::New(localTemplate); - m_hostTemplate->SetClassName(v8::String::New(objectName)); -} +class BackingStoreCompositingSurface; +class WebPagePrivate; -BoundObject::~BoundObject() -{ - m_hostTemplate.Dispose(); -} +class GLES2Context : public Platform::Graphics::GLES2Context { + WTF_MAKE_NONCOPYABLE(GLES2Context); +public: + static PassOwnPtr<GLES2Context> create(WebPagePrivate*); + ~GLES2Context(); + Platform::IntSize surfaceSize() const; + bool makeCurrent(); + bool swapBuffers(); -void BoundObject::addProtoFunction(const char* name, v8::InvocationCallback callback) -{ - v8::Context::Scope contextScope(m_context); - v8::Local<v8::Signature> signature = v8::Signature::New(m_hostTemplate); - v8::Local<v8::ObjectTemplate> proto = m_hostTemplate->PrototypeTemplate(); - v8::Local<v8::External> v8This = v8::External::New(m_v8This); - proto->Set( - v8::String::New(name), - v8::FunctionTemplate::New( - callback, - v8This, - signature), - static_cast<v8::PropertyAttribute>(v8::DontDelete)); -} +private: + GLES2Context(WebPagePrivate*); + BackingStoreCompositingSurface* compositingSurface() const; + Platform::Graphics::Buffer* buffer() const; -void BoundObject::build() -{ - v8::Context::Scope contextScope(m_context); - v8::Local<v8::Function> constructor = m_hostTemplate->GetFunction(); - v8::Local<v8::Object> boundObject = WebCore::SafeAllocation::newInstance(constructor); - - v8::Handle<v8::Object> global = m_context->Global(); - global->Set(v8::String::New(m_objectName), boundObject); -} + Platform::Graphics::Window* m_window; +}; } // namespace WebKit +} // namespace BlackBerry + +#endif diff --git a/Source/WebKit/blackberry/WebKitSupport/InPageSearchManager.cpp b/Source/WebKit/blackberry/WebKitSupport/InPageSearchManager.cpp new file mode 100644 index 000000000..ae0402100 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/InPageSearchManager.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "InPageSearchManager.h" + +#include "Document.h" +#include "DocumentMarkerController.h" +#include "Editor.h" +#include "Frame.h" +#include "Page.h" +#include "WebPage_p.h" + +static const int TextMatchMarkerLimit = 100; + +using namespace WebCore; + +namespace BlackBerry { +namespace WebKit { + +InPageSearchManager::InPageSearchManager(WebPagePrivate* page) + : m_webPage(page) + , m_activeMatch(0) +{ +} + +InPageSearchManager::~InPageSearchManager() +{ +} + +bool InPageSearchManager::findNextString(const String& text, bool forward) +{ + if (!text.length()) { + clearTextMatches(); + m_activeSearchString = String(); + return false; + } + + if (m_activeSearchString != text) { + clearTextMatches(); + m_activeSearchString = text; + m_activeMatchCount = m_webPage->m_page->markAllMatchesForText(text, WebCore::CaseInsensitive, true, TextMatchMarkerLimit); + } else + setMarkerActive(m_activeMatch.get(), false); + + if (!m_activeMatchCount) + return false; + + const FindOptions findOptions = (forward ? 0 : WebCore::Backwards) + | WebCore::CaseInsensitive + | WebCore::WrapAround; // TODO should wrap around in page, not in frame + + // TODO StartInSelection + + m_activeMatch = m_webPage->mainFrame()->editor()->findStringAndScrollToVisible(text, m_activeMatch.get(), findOptions); + setMarkerActive(m_activeMatch.get(), true); + + return true; +} + +void InPageSearchManager::clearTextMatches() +{ + m_webPage->m_page->unmarkAllTextMatches(); + m_activeMatch = 0; +} + +void InPageSearchManager::setMarkerActive(WebCore::Range* range, bool active) +{ + if (!range) + return; + WebCore::Document* doc = m_webPage->mainFrame()->document(); + if (!doc) + return; + doc->markers()->setMarkersActive(range, active); +} + +} +} diff --git a/Source/WebKit/blackberry/WebKitSupport/InPageSearchManager.h b/Source/WebKit/blackberry/WebKitSupport/InPageSearchManager.h new file mode 100644 index 000000000..1f6bbb535 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/InPageSearchManager.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef InPageSearchManager_h +#define InPageSearchManager_h + +#include "WTFString.h" + +#include <wtf/RefPtr.h> + +namespace WebCore { +class Range; +} + +namespace BlackBerry { + +namespace WebKit { + +class WebPagePrivate; + +class InPageSearchManager { +public: + InPageSearchManager(WebPagePrivate*); + ~InPageSearchManager(); + + bool findNextString(const String& text, bool forward); + +private: + void clearTextMatches(); + void setMarkerActive(WebCore::Range*, bool active); + + WebPagePrivate* m_webPage; + RefPtr<WebCore::Range> m_activeMatch; + String m_activeSearchString; + int m_activeMatchCount; +}; + +} +} + +#endif // InPageSearchManager_h diff --git a/Source/WebKit/blackberry/WebKitSupport/InRegionScrollableArea.cpp b/Source/WebKit/blackberry/WebKitSupport/InRegionScrollableArea.cpp new file mode 100644 index 000000000..5eac31a30 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/InRegionScrollableArea.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "InRegionScrollableArea.h" + +#include "Frame.h" +#include "NotImplemented.h" +#include "RenderBox.h" +#include "RenderLayer.h" +#include "RenderObject.h" +#include "RenderView.h" +#include "WebPage_p.h" + +using namespace WebCore; + +namespace BlackBerry { +namespace WebKit { + +InRegionScrollableArea::InRegionScrollableArea() + : m_webPage(0) + , m_layer(0) +{ +} + +InRegionScrollableArea::InRegionScrollableArea(WebPagePrivate* webPage, RenderLayer* layer) + : m_webPage(webPage) + , m_layer(layer) +{ + ASSERT(webPage); + ASSERT(layer); + m_isNull = false; + + // FIXME: Add an ASSERT here as the 'layer' must be scrollable. + + RenderObject* layerRenderer = layer->renderer(); + ASSERT(layerRenderer); + + if (layerRenderer->isRenderView()) { // #document case + + FrameView* view = toRenderView(layerRenderer)->frameView(); + ASSERT(view); + + Frame* frame = view->frame(); + ASSERT_UNUSED(frame, frame); + + m_scrollPosition = m_webPage->mapToTransformed(view->scrollPosition()); + m_contentsSize = m_webPage->mapToTransformed(view->contentsSize()); + m_viewportRect = m_webPage->mapToTransformed(view->visibleContentRect(false /*includeScrollbars*/)); + + m_visibleWindowRect = m_webPage->mapToTransformed(m_webPage->getRecursiveVisibleWindowRect(view)); + IntRect transformedWindowRect = IntRect(IntPoint::zero(), m_webPage->transformedViewportSize()); + m_visibleWindowRect.intersect(transformedWindowRect); + + m_scrollsHorizontally = view->contentsWidth() > view->visibleWidth(); + m_scrollsVertically = view->contentsHeight() > view->visibleHeight(); + + m_minimumScrollPosition = m_webPage->mapToTransformed(calculateMinimumScrollPosition( + view->visibleContentRect().size(), + 0.0 /*overscrollLimit*/)); + m_maximumScrollPosition = m_webPage->mapToTransformed(calculateMaximumScrollPosition( + view->visibleContentRect().size(), + view->contentsSize(), + 0.0 /*overscrollLimit*/)); + + } else { // RenderBox-based elements case (scrollable boxes (div's, p's, textarea's, etc)). + + RenderBox* box = m_layer->renderBox(); + ASSERT(box); + ASSERT(box->canBeScrolledAndHasScrollableArea()); + + ScrollableArea* scrollableArea = static_cast<ScrollableArea*>(m_layer); + m_scrollPosition = m_webPage->mapToTransformed(scrollableArea->scrollPosition()); + m_contentsSize = m_webPage->mapToTransformed(scrollableArea->contentsSize()); + m_viewportRect = m_webPage->mapToTransformed(scrollableArea->visibleContentRect(false /*includeScrollbars*/)); + + m_visibleWindowRect = m_layer->renderer()->absoluteClippedOverflowRect(); + m_visibleWindowRect = m_layer->renderer()->frame()->view()->contentsToWindow(m_visibleWindowRect); + IntRect visibleFrameWindowRect = m_webPage->getRecursiveVisibleWindowRect(m_layer->renderer()->frame()->view()); + m_visibleWindowRect.intersect(visibleFrameWindowRect); + m_visibleWindowRect = m_webPage->mapToTransformed(m_visibleWindowRect); + IntRect transformedWindowRect = IntRect(IntPoint::zero(), m_webPage->transformedViewportSize()); + m_visibleWindowRect.intersect(transformedWindowRect); + + m_scrollsHorizontally = box->scrollWidth() != box->clientWidth() && box->scrollsOverflowX(); + m_scrollsVertically = box->scrollHeight() != box->clientHeight() && box->scrollsOverflowY(); + + m_minimumScrollPosition = m_webPage->mapToTransformed(calculateMinimumScrollPosition( + Platform::IntSize(box->clientWidth(), box->clientHeight()), + 0.0 /*overscrollLimit*/)); + m_maximumScrollPosition = m_webPage->mapToTransformed(calculateMaximumScrollPosition( + Platform::IntSize(box->clientWidth(), box->clientHeight()), + Platform::IntSize(box->scrollWidth(), box->scrollHeight()), + 0.0 /*overscrollLimit*/)); + } +} + +Platform::IntPoint InRegionScrollableArea::calculateMinimumScrollPosition(const Platform::IntSize& viewportSize, float overscrollLimitFactor) const +{ + // FIXME: Eventually we should support overscroll like iOS5 does. + ASSERT(!allowsOverscroll()); + + return Platform::IntPoint(-(viewportSize.width() * overscrollLimitFactor), + -(viewportSize.height() * overscrollLimitFactor)); +} + +Platform::IntPoint InRegionScrollableArea::calculateMaximumScrollPosition(const Platform::IntSize& viewportSize, const Platform::IntSize& contentsSize, float overscrollLimitFactor) const +{ + // FIXME: Eventually we should support overscroll like iOS5 does. + ASSERT(!allowsOverscroll()); + + return Platform::IntPoint(std::max(contentsSize.width() - viewportSize.width(), 0) + overscrollLimitFactor, + std::max(contentsSize.height() - viewportSize.height(), 0) + overscrollLimitFactor); +} + +RenderLayer* InRegionScrollableArea::layer() const +{ + ASSERT(!m_isNull); + return m_layer; +} +} + +} diff --git a/Source/WebKit/blackberry/WebKitSupport/InRegionScrollableArea.h b/Source/WebKit/blackberry/WebKitSupport/InRegionScrollableArea.h new file mode 100644 index 000000000..9467b9bc5 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/InRegionScrollableArea.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef InRegionScrollableArea_h +#define InRegionScrollableArea_h + +#include <BlackBerryPlatformPrimitives.h> +#include <interaction/ScrollViewBase.h> + +namespace WebCore { +class RenderLayer; +} + +namespace BlackBerry { +namespace WebKit { + +class WebPagePrivate; + +class InRegionScrollableArea : public Platform::ScrollViewBase { +public: + + InRegionScrollableArea(); + InRegionScrollableArea(WebPagePrivate*, WebCore::RenderLayer*); + + WebCore::RenderLayer* layer() const; + +private: + Platform::IntPoint calculateMinimumScrollPosition(const Platform::IntSize& viewportSize, float overscrollLimitFactor) const; + Platform::IntPoint calculateMaximumScrollPosition(const Platform::IntSize& viewportSize, const Platform::IntSize& contentsSize, float overscrollLimitFactor) const; + + WebPagePrivate* m_webPage; + WebCore::RenderLayer* m_layer; +}; + +} +} + +#endif diff --git a/Source/WebKit/blackberry/WebKitSupport/InputHandler.cpp b/Source/WebKit/blackberry/WebKitSupport/InputHandler.cpp index ad555dae7..27b941e6f 100644 --- a/Source/WebKit/blackberry/WebKitSupport/InputHandler.cpp +++ b/Source/WebKit/blackberry/WebKitSupport/InputHandler.cpp @@ -110,11 +110,13 @@ InputHandler::InputHandler(WebPagePrivate* page) : m_webPage(page) , m_currentFocusElement(0) , m_processingChange(false) - , m_navigationMode(false) + , m_changingFocus(false) , m_currentFocusElementType(TextEdit) , m_currentFocusElementTextEditMask(DEFAULT_STYLE) , m_composingTextStart(0) , m_composingTextEnd(0) + , m_pendingKeyboardVisibilityChange(NoChange) + , m_delayKeyboardVisibilityChange(false) { } @@ -223,7 +225,7 @@ BlackBerryInputType InputHandler::elementType(Element* element) const void InputHandler::nodeFocused(Node* node) { if (isActiveTextEdit() && m_currentFocusElement == node) { - setNavigationMode(true); + notifyClientOfKeyboardVisibilityChange(true); return; } @@ -391,10 +393,10 @@ void InputHandler::setElementUnfocused(bool refocusOccuring) // End any composition that is in progress. finishComposition(); - // Send change notifications. Only cancel navigation mode if we are not - // refocusing to avoid flashing the keyboard when switching between two - // input fields. - setNavigationMode(false, !refocusOccuring); + // Only hide the keyboard if we aren't refocusing on a new input field. + if (!refocusOccuring) + notifyClientOfKeyboardVisibilityChange(false); + m_webPage->m_client->inputFocusLost(); m_webPage->m_selectionHandler->selectionPositionChanged(); } @@ -410,29 +412,37 @@ bool InputHandler::shouldAcceptInputFocus() if (m_webPage->m_dumpRenderTree) return true; - if (BlackBerry::Platform::Settings::get()->alwaysShowKeyboardOnFocus()) + if (BlackBerry::Platform::Settings::get()->alwaysShowKeyboardOnFocus()) { + FocusLog(BlackBerry::Platform::LogLevelInfo, "InputHandler::shouldAcceptInputFocus alwaysShowKeyboardOnFocus is active."); return true; + } - Frame* mainFrame = m_webPage->m_page->mainFrame(); Frame* focusedFrame = m_webPage->focusedOrMainFrame(); - if (mainFrame && mainFrame->document() && focusedFrame && focusedFrame->document()) { - // Any user action should be respected. Mouse will be down when touch is - // used to focus. - if (focusedFrame->eventHandler()->mousePressed()) - return true; + if (!focusedFrame) { + FocusLog(BlackBerry::Platform::LogLevelInfo, "InputHandler::shouldAcceptInputFocus Frame not valid."); + return false; + } - // Make sure the main frame is not still loading. - if (mainFrame->loader()->isLoading()) - return false; + // Any user action should be respected. Mouse will be down when touch is + // used to focus. + if (focusedFrame->eventHandler()->mousePressed()) { + FocusLog(BlackBerry::Platform::LogLevelInfo, "InputHandler::shouldAcceptInputFocus Mouse is pressed focusing."); + return true; + } - // Make sure the focused frame is loaded. - if (!focusedFrame->loader()->frameHasLoaded()) - return false; + if (!m_webPage->m_client->hasKeyboardFocus()) { + FocusLog(BlackBerry::Platform::LogLevelInfo, "InputHandler::shouldAcceptInputFocus Client does not have input focus."); + return false; + } - // Make sure the focused frame is not processing load events. - return !focusedFrame->document()->processingLoadEvent(); + if (m_webPage->isLoading()) { + FocusLog(BlackBerry::Platform::LogLevelInfo, "InputHandler::shouldAcceptInputFocus Webpage is loading."); + return false; } - return false; + + // Make sure the focused frame is not processing load events. + FocusLog(BlackBerry::Platform::LogLevelInfo, "InputHandler::shouldAcceptInputFocus returning state of processingLoadEvent (%s).", !focusedFrame->document()->processingLoadEvent() ? "true" : "false"); + return !focusedFrame->document()->processingLoadEvent(); } void InputHandler::setElementFocused(Element* element) @@ -440,9 +450,15 @@ void InputHandler::setElementFocused(Element* element) ASSERT(DOMSupport::isTextBasedContentEditableElement(element)); ASSERT(element->document() && element->document()->frame()); - if (!shouldAcceptInputFocus()) { - // Remove the focus from this element. + if (!m_changingFocus && !shouldAcceptInputFocus()) { + // Remove the focus from this element, but guard against recursion by + // allowing a refocus during the blur to continue. + // THIS IS A HACK that needs to be fixed. Instead of blur the field, + // the frame or frame selection should be blurred. Google bypasses these + // though so it can't be done right now. + m_changingFocus = true; element->blur(); + m_changingFocus = false; return; } @@ -459,8 +475,9 @@ void InputHandler::setElementFocused(Element* element) FocusLog(BlackBerry::Platform::LogLevelInfo, "InputHandler::setElementFocused, Type=%d, Style=%d", type, m_currentFocusElementTextEditMask); - m_webPage->m_client->inputFocusGained(type, m_currentFocusElementTextEditMask); - m_navigationMode = true; + m_webPage->m_client->inputFocusGained(type, + m_currentFocusElementTextEditMask, + m_delayKeyboardVisibilityChange /* wait for explicit keyboard show call */); handleInputLocaleChanged(m_webPage->m_webSettings->isWritingDirectionRTL()); } @@ -528,7 +545,7 @@ void InputHandler::nodeTextChanged(const Node* node) void InputHandler::ensureFocusTextElementVisible(CaretScrollType scrollType) { - if (!m_currentFocusElement || !m_navigationMode || !m_currentFocusElement->document()) + if (!m_currentFocusElement || !m_currentFocusElement->document()) return; if (!BlackBerry::Platform::Settings::get()->allowCenterScrollAdjustmentForInputFields() && scrollType != EdgeIfNeeded) @@ -706,34 +723,36 @@ void InputHandler::frameUnloaded(Frame* frame) setElementUnfocused(false /*refocusOccuring*/); } -void InputHandler::setNavigationMode(bool active, bool sendMessage) +void InputHandler::setDelayKeyboardVisibilityChange(bool value) { - if (active && !isActiveTextEdit()) { - if (!m_navigationMode) - return; + m_delayKeyboardVisibilityChange = value; + m_pendingKeyboardVisibilityChange = NoChange; +} - // We can't be active if there is no element. Send out notification that we - // aren't in navigation mode. - active = false; +void InputHandler::processPendingKeyboardVisibilityChange() +{ + if (!m_delayKeyboardVisibilityChange) { + ASSERT(m_pendingKeyboardVisibilityChange == NoChange); + return; } - // Don't send the change if it's setting the event setting navigationMode true - // if we are already in navigation mode and this is a navigation move event. - // We need to send the event when it's triggered by a touch event or mouse - // event to allow display of the VKB, but do not want to send it when it's - // triggered by a navigation event as it has no effect. - // Touch events are simulated as mouse events so mousePressed will be active - // when it is a re-entry event. - // See RIM Bugs #369 & #878. - if (active && active == m_navigationMode && !m_webPage->m_mainFrame->eventHandler()->mousePressed()) + m_delayKeyboardVisibilityChange = false; + + if (m_pendingKeyboardVisibilityChange == NoChange) return; - m_navigationMode = active; + notifyClientOfKeyboardVisibilityChange(m_pendingKeyboardVisibilityChange == Visible); + m_pendingKeyboardVisibilityChange = NoChange; +} - InputLog(BlackBerry::Platform::LogLevelInfo, "InputHandler::setNavigationMode %s, %s", active ? "true" : "false", sendMessage ? "message sent" : "message not sent"); +void InputHandler::notifyClientOfKeyboardVisibilityChange(bool visible) +{ + if (!m_delayKeyboardVisibilityChange) { + m_webPage->showVirtualKeyboard(visible); + return; + } - if (sendMessage) - m_webPage->m_client->inputSetNavigationMode(active); + m_pendingKeyboardVisibilityChange = visible ? Visible : NotVisible; } bool InputHandler::selectionAtStartOfElement() @@ -856,7 +875,7 @@ WebCore::IntRect InputHandler::rectForCaret(int index) ASSERT(m_currentFocusElement->document() && m_currentFocusElement->document()->frame()); - if (index < 0 || index > elementText().length()) { + if (index < 0 || index > static_cast<int>(elementText().length())) { // Invalid request. return WebCore::IntRect(); } @@ -920,68 +939,6 @@ bool InputHandler::handleKeyboardInput(const BlackBerry::Platform::KeyboardEvent return keyboardEventHandled; } -bool InputHandler::handleNavigationMove(unsigned short character, bool shiftDown, bool altDown, bool canExitField) -{ - InputLog(BlackBerry::Platform::LogLevelInfo, "InputHandler::handleNavigationMove received character=%lc", character); - - bool eventHandled = false; - ASSERT(m_webPage->m_page->focusController()); - if (Frame* focusedFrame = m_webPage->m_page->focusController()->focusedFrame()) { - // If alt is down, do not break out of the field. - if (canExitField && !altDown) { - if ((character == KEYCODE_LEFT || character == KEYCODE_UP) && selectionAtStartOfElement() - || (character == KEYCODE_RIGHT || character == KEYCODE_DOWN) && selectionAtEndOfElement()) { - setNavigationMode(false); - return true; - } - } - - switch (character) { - case KEYCODE_LEFT: - if (altDown && shiftDown) - eventHandled = focusedFrame->editor()->command("MoveToBeginningOfLineAndModifySelection").execute(); - else if (altDown) - eventHandled = focusedFrame->editor()->command("MoveToBeginningOfLine").execute(); - else if (shiftDown) - eventHandled = focusedFrame->editor()->command("MoveLeftAndModifySelection").execute(); - else - eventHandled = focusedFrame->editor()->command("MoveLeft").execute(); - break; - case KEYCODE_RIGHT: - if (altDown && shiftDown) - eventHandled = focusedFrame->editor()->command("MoveToEndOfLineAndModifySelection").execute(); - else if (altDown) - eventHandled = focusedFrame->editor()->command("MoveToEndOfLine").execute(); - else if (shiftDown) - eventHandled = focusedFrame->editor()->command("MoveRightAndModifySelection").execute(); - else - eventHandled = focusedFrame->editor()->command("MoveRight").execute(); - break; - case KEYCODE_UP: - if (altDown && shiftDown) - eventHandled = focusedFrame->editor()->command("MoveToBeginningOfDocumentAndModifySelection").execute(); - else if (altDown) - eventHandled = focusedFrame->editor()->command("MoveToBeginningOfDocument").execute(); - else if (shiftDown) - eventHandled = focusedFrame->editor()->command("MoveUpAndModifySelection").execute(); - else - eventHandled = focusedFrame->editor()->command("MoveUp").execute(); - break; - case KEYCODE_DOWN: - if (altDown && shiftDown) - eventHandled = focusedFrame->editor()->command("MoveToEndOfDocumentAndModifySelection").execute(); - else if (altDown) - eventHandled = focusedFrame->editor()->command("MoveToEndOfDocument").execute(); - else if (shiftDown) - eventHandled = focusedFrame->editor()->command("MoveDownAndModifySelection").execute(); - else - eventHandled = focusedFrame->editor()->command("MoveDown").execute(); - break; - } - } - return eventHandled; -} - bool InputHandler::deleteSelection() { if (!isActiveTextEdit()) diff --git a/Source/WebKit/blackberry/WebKitSupport/InputHandler.h b/Source/WebKit/blackberry/WebKitSupport/InputHandler.h index ba7eb3e7b..1b64a78b1 100644 --- a/Source/WebKit/blackberry/WebKitSupport/InputHandler.h +++ b/Source/WebKit/blackberry/WebKitSupport/InputHandler.h @@ -63,7 +63,6 @@ public: void frameUnloaded(WebCore::Frame*); bool handleKeyboardInput(const BlackBerry::Platform::KeyboardEvent&, bool changeIsPartOfComposition = false); - bool handleNavigationMove(const unsigned short character, bool shiftDown, bool altDown, bool canExitField = true); bool deleteSelection(); void insertText(const WTF::String&); @@ -77,11 +76,14 @@ public: void setInputValue(const WTF::String&); + void setDelayKeyboardVisibilityChange(bool value); + void processPendingKeyboardVisibilityChange(); + + void notifyClientOfKeyboardVisibilityChange(bool visible); + bool isInputMode() const { return isActiveTextEdit(); } bool isMultilineInputMode() const { return isActiveTextEdit() && elementType(m_currentFocusElement.get()) == BlackBerry::Platform::InputTypeTextArea; } - void setNavigationMode(bool active, bool sendMessage = true); - void ensureFocusElementVisible(bool centerFieldInDisplay = true); void handleInputLocaleChanged(bool isRTL); @@ -117,6 +119,8 @@ public: bool shouldAcceptInputFocus(); private: + enum PendingKeyboardStateChange { NoChange, Visible, NotVisible }; + void setElementFocused(WebCore::Element*); void setPluginFocused(WebCore::Element*); void setElementUnfocused(bool refocusOccuring = false); @@ -175,12 +179,16 @@ private: RefPtr<WebCore::Element> m_currentFocusElement; bool m_processingChange; - bool m_navigationMode; + bool m_changingFocus; + FocusElementType m_currentFocusElementType; int m_currentFocusElementTextEditMask; int m_composingTextStart; int m_composingTextEnd; + + PendingKeyboardStateChange m_pendingKeyboardVisibilityChange; + bool m_delayKeyboardVisibilityChange; }; } diff --git a/Source/WebKit/blackberry/WebKitSupport/RenderQueue.cpp b/Source/WebKit/blackberry/WebKitSupport/RenderQueue.cpp new file mode 100644 index 000000000..1f320b9a8 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/RenderQueue.cpp @@ -0,0 +1,910 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "RenderQueue.h" + +#include "BackingStore_p.h" +#include "WebPageClient.h" +#include "WebPage_p.h" + +#define DEBUG_RENDER_QUEUE 0 +#define DEBUG_RENDER_QUEUE_SORT 0 + +#if DEBUG_RENDER_QUEUE +#include <BlackBerryPlatformLog.h> +#include <wtf/CurrentTime.h> +#endif + +namespace BlackBerry { +namespace WebKit { + +template<SortDirection sortDirection> +static inline int compareRectOneDirection(const Platform::IntRect& r1, const Platform::IntRect& r2) +{ + switch (sortDirection) { + case LeftToRight: + return r1.x() - r2.x(); + case RightToLeft: + return r2.x() - r1.x(); + case TopToBottom: + return r1.y() - r2.y(); + case BottomToTop: + return r2.y() - r1.y(); + default: + break; + } + ASSERT_NOT_REACHED(); + return 0; +} + +template<SortDirection primarySortDirection, SortDirection secondarySortDirection> +static bool rectIsLessThan(const Platform::IntRect& r1, const Platform::IntRect& r2) +{ + int primaryResult = compareRectOneDirection<primarySortDirection>(r1, r2); + if (primaryResult || secondarySortDirection == primarySortDirection) + return primaryResult < 0; + return compareRectOneDirection<secondarySortDirection>(r1, r2) < 0; +} + +typedef bool (*FuncRectLessThan)(const Platform::IntRect& r1, const Platform::IntRect& r2); +static FuncRectLessThan rectLessThanFunction(SortDirection primary, SortDirection secondary) +{ + static FuncRectLessThan s_rectLessThanFunctions[NumSortDirections][NumSortDirections] = { { 0 } }; + static bool s_initialized = false; + if (!s_initialized) { +#define ADD_COMPARE_FUNCTION(_primary, _secondary) \ + s_rectLessThanFunctions[_primary][_secondary] = rectIsLessThan<_primary, _secondary> + + ADD_COMPARE_FUNCTION(LeftToRight, LeftToRight); + ADD_COMPARE_FUNCTION(LeftToRight, RightToLeft); + ADD_COMPARE_FUNCTION(LeftToRight, TopToBottom); + ADD_COMPARE_FUNCTION(LeftToRight, BottomToTop); + + ADD_COMPARE_FUNCTION(RightToLeft, LeftToRight); + ADD_COMPARE_FUNCTION(RightToLeft, RightToLeft); + ADD_COMPARE_FUNCTION(RightToLeft, TopToBottom); + ADD_COMPARE_FUNCTION(RightToLeft, BottomToTop); + + ADD_COMPARE_FUNCTION(TopToBottom, LeftToRight); + ADD_COMPARE_FUNCTION(TopToBottom, RightToLeft); + ADD_COMPARE_FUNCTION(TopToBottom, TopToBottom); + ADD_COMPARE_FUNCTION(TopToBottom, BottomToTop); + + ADD_COMPARE_FUNCTION(BottomToTop, LeftToRight); + ADD_COMPARE_FUNCTION(BottomToTop, RightToLeft); + ADD_COMPARE_FUNCTION(BottomToTop, TopToBottom); + ADD_COMPARE_FUNCTION(BottomToTop, BottomToTop); +#undef ADD_COMPARE_FUNCTION + + s_initialized = true; + } + + return s_rectLessThanFunctions[primary][secondary]; +} + +class RectLessThan { +public: + RectLessThan(SortDirection primarySortDirection, SortDirection secondarySortDirection) + : m_rectIsLessThan(rectLessThanFunction(primarySortDirection, secondarySortDirection)) + { + } + + bool operator()(const Platform::IntRect& r1, const Platform::IntRect& r2) + { + return m_rectIsLessThan(r1, r2); + } + +private: + FuncRectLessThan m_rectIsLessThan; +}; + +class RenderRectLessThan { +public: + RenderRectLessThan(SortDirection primarySortDirection, SortDirection secondarySortDirection) + : m_rectIsLessThan(rectLessThanFunction(primarySortDirection, secondarySortDirection)) + { + } + + bool operator()(const RenderRect& r1, const RenderRect& r2) + { + return m_rectIsLessThan(r1.subRects()[0], r2.subRects()[0]); + } + +private: + FuncRectLessThan m_rectIsLessThan; +}; + +RenderRect::RenderRect(const Platform::IntPoint& location, const Platform::IntSize& size, int splittingFactor) + : Platform::IntRect(location, size) + , m_splittingFactor(0) + , m_primarySortDirection(TopToBottom) + , m_secondarySortDirection(LeftToRight) +{ + initialize(splittingFactor); +} + +RenderRect::RenderRect(int x, int y, int width, int height, int splittingFactor) + : Platform::IntRect(x, y, width, height) + , m_splittingFactor(0) + , m_primarySortDirection(TopToBottom) + , m_secondarySortDirection(LeftToRight) +{ + initialize(splittingFactor); +} + +void RenderRect::initialize(int splittingFactor) +{ + m_subRects.push_back(*this); + for (int i = 0; i < splittingFactor; ++i) + split(); + quickSort(); +} + +static void splitRectInHalfAndAddToList(const Platform::IntRect& rect, bool vertical, IntRectList& renderRectList) +{ + if (vertical) { + int width1 = static_cast<int>(ceilf(rect.width() / 2.0)); + int width2 = static_cast<int>(floorf(rect.width() / 2.0)); + renderRectList.push_back(Platform::IntRect(rect.x(), rect.y(), width1, rect.height())); + renderRectList.push_back(Platform::IntRect(rect.x() + width1, rect.y(), width2, rect.height())); + } else { + int height1 = static_cast<int>(ceilf(rect.height() / 2.0)); + int height2 = static_cast<int>(floorf(rect.height() / 2.0)); + renderRectList.push_back(Platform::IntRect(rect.x(), rect.y(), rect.width(), height1)); + renderRectList.push_back(Platform::IntRect(rect.x(), rect.y() + height1, rect.width(), height2)); + } +} + +void RenderRect::split() +{ + ++m_splittingFactor; + + bool vertical = !(m_splittingFactor % 2); + + IntRectList subRects; + for (size_t i = 0; i < m_subRects.size(); ++i) + splitRectInHalfAndAddToList(m_subRects.at(i), vertical, subRects); + m_subRects.swap(subRects); +} + +Platform::IntRect RenderRect::rectForRendering() +{ + ASSERT(!m_subRects.empty()); + Platform::IntRect rect = m_subRects[0]; + m_subRects.erase(m_subRects.begin()); + return rect; +} + +void RenderRect::updateSortDirection(SortDirection primary, SortDirection secondary) +{ + if (primary == m_primarySortDirection && secondary == m_secondarySortDirection) + return; + + m_primarySortDirection = primary; + m_secondarySortDirection = secondary; + + quickSort(); +} + +void RenderRect::quickSort() +{ + std::sort(m_subRects.begin(), m_subRects.begin(), RectLessThan(m_primarySortDirection, m_secondarySortDirection)); +} + +RenderQueue::RenderQueue(BackingStorePrivate* parent) + : m_parent(parent) + , m_rectsAddedToRegularRenderJobsInCurrentCycle(false) + , m_currentRegularRenderJobsBatchUnderPressure(false) + , m_primarySortDirection(TopToBottom) + , m_secondarySortDirection(LeftToRight) +{ +} + +void RenderQueue::reset() +{ + m_rectsAddedToRegularRenderJobsInCurrentCycle = false; + m_currentRegularRenderJobsBatchUnderPressure = false; + m_primarySortDirection = TopToBottom; + m_secondarySortDirection = LeftToRight; + m_visibleZoomJobs.clear(); + m_visibleScrollJobs.clear(); + m_visibleScrollJobsCompleted.clear(); + m_nonVisibleScrollJobs.clear(); + m_nonVisibleScrollJobsCompleted.clear(); + m_regularRenderJobsRegion = Platform::IntRectRegion(); + m_currentRegularRenderJobsBatch.clear(); + m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion(); + m_regularRenderJobsNotRenderedRegion = Platform::IntRectRegion(); + m_parent->stopRenderTimer(); + ASSERT(isEmpty()); +} + +int RenderQueue::splittingFactor(const Platform::IntRect& rect) const +{ + // This method is used to split up regular render rect jobs and we want it to + // to be zoom invariant with respect to WebCore. In other words, if WebCore sends + // us a rect of viewport size to invalidate at zoom 1.0 then we split that up + // in the exact same way we would at zoom 2.0. The amount of content that is + // rendered in any one pass should stay fixed with regard to the zoom level. + Platform::IntRect untransformedRect = m_parent->m_webPage->d->mapFromTransformed(rect); + double rectArea = untransformedRect.width() * untransformedRect.height(); + Platform::IntSize defaultMaxLayoutSize = WebPagePrivate::defaultMaxLayoutSize(); + double maxArea = defaultMaxLayoutSize.width() * defaultMaxLayoutSize.height(); + + const unsigned splitFactor = 1 << 0; + double renderRectArea = maxArea / splitFactor; + return ceil(log(rectArea / renderRectArea) / log(2.0)); +} + +RenderRect RenderQueue::convertToRenderRect(const Platform::IntRect& rect) const +{ + return RenderRect(rect.location(), rect.size(), splittingFactor(rect)); +} + +bool RenderQueue::isEmpty(bool shouldPerformRegularRenderJobs) const +{ + return m_visibleZoomJobs.empty() && m_visibleScrollJobs.empty() + && (!shouldPerformRegularRenderJobs || m_currentRegularRenderJobsBatch.empty()) + && (!shouldPerformRegularRenderJobs || m_regularRenderJobsRegion.isEmpty()) + && m_nonVisibleScrollJobs.empty(); +} + +bool RenderQueue::hasCurrentRegularRenderJob() const +{ + return !m_currentRegularRenderJobsBatch.empty() || !m_regularRenderJobsRegion.isEmpty(); +} + +bool RenderQueue::hasCurrentVisibleZoomJob() const +{ + return !m_visibleZoomJobs.empty(); +} + +bool RenderQueue::hasCurrentVisibleScrollJob() const +{ + return !m_visibleScrollJobs.empty(); +} + +bool RenderQueue::isCurrentVisibleScrollJob(const Platform::IntRect& rect) const +{ + return std::find(m_visibleScrollJobs.begin(), m_visibleScrollJobs.end(), rect) != m_visibleScrollJobs.end(); +} + +bool RenderQueue::isCurrentVisibleScrollJobCompleted(const Platform::IntRect& rect) const +{ + return std::find(m_visibleScrollJobsCompleted.begin(), m_visibleScrollJobsCompleted.end(), rect) != m_visibleScrollJobsCompleted.end(); +} + +bool RenderQueue::isCurrentRegularRenderJob(const Platform::IntRect& rect) const +{ + return m_regularRenderJobsRegion.isRectInRegion(rect) == Platform::IntRectRegion::ContainedInRegion + || m_currentRegularRenderJobsBatchRegion.isRectInRegion(rect) == Platform::IntRectRegion::ContainedInRegion; +} + +bool RenderQueue::currentRegularRenderJobBatchUnderPressure() const +{ + return m_currentRegularRenderJobsBatchUnderPressure; +} + +void RenderQueue::setCurrentRegularRenderJobBatchUnderPressure(bool currentRegularRenderJobsBatchUnderPressure) +{ + m_currentRegularRenderJobsBatchUnderPressure = currentRegularRenderJobsBatchUnderPressure; +} + +void RenderQueue::eventQueueCycled() +{ + // Called by the backing store when the event queue has cycled to allow the + // render queue to determine if the regular render jobs are under pressure. + if (m_rectsAddedToRegularRenderJobsInCurrentCycle && m_currentRegularRenderJobsBatchRegion.isEmpty()) + m_currentRegularRenderJobsBatchUnderPressure = true; + m_rectsAddedToRegularRenderJobsInCurrentCycle = false; +} + +void RenderQueue::addToQueue(JobType type, const IntRectList& rectList) +{ + for (size_t i = 0; i < rectList.size(); ++i) + addToQueue(type, rectList.at(i)); +} + +void RenderQueue::addToQueue(JobType type, const Platform::IntRect& rect) +{ + if (type == NonVisibleScroll && std::find(m_visibleScrollJobs.begin(), m_visibleScrollJobs.end(), rect) != m_visibleScrollJobs.end()) + return; // |rect| is in a higher priority queue. + + switch (type) { + case VisibleZoom: + addToScrollZoomQueue(convertToRenderRect(rect), &m_visibleZoomJobs); + return; + case VisibleScroll: + addToScrollZoomQueue(convertToRenderRect(rect), &m_visibleScrollJobs); + return; + case RegularRender: + { + // Flag that we added rects in the current event queue cycle. + m_rectsAddedToRegularRenderJobsInCurrentCycle = true; + + // We try and detect if this newly added rect intersects or is contained in the currently running + // batch of render jobs. If so, then we have to start the batch over since we decompose individual + // rects into subrects and might have already rendered one of them. If the web page's content has + // changed state then this can lead to artifacts. We mark this by noting the batch is now under pressure + // and the backingstore will attempt to clear it at the next available opportunity. + Platform::IntRectRegion::IntersectionState state = m_currentRegularRenderJobsBatchRegion.isRectInRegion(rect); + if (state == Platform::IntRectRegion::ContainedInRegion || state == Platform::IntRectRegion::PartiallyContainedInRegion) { + m_regularRenderJobsRegion = Platform::IntRectRegion::unionRegions(m_regularRenderJobsRegion, m_currentRegularRenderJobsBatchRegion); + m_currentRegularRenderJobsBatch.clear(); + m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion(); + m_currentRegularRenderJobsBatchUnderPressure = true; + } + addToRegularQueue(rect); + } + return; + case NonVisibleScroll: + addToScrollZoomQueue(convertToRenderRect(rect), &m_nonVisibleScrollJobs); + return; + } + ASSERT_NOT_REACHED(); +} + +void RenderQueue::addToRegularQueue(const Platform::IntRect& rect) +{ +#if DEBUG_RENDER_QUEUE + if (m_regularRenderJobsRegion.isRectInRegion(rect) != Platform::IntRectRegion::ContainedInRegion) { + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::addToRegularQueue %d,%d %dx%d", + rect.x(), rect.y(), rect.width(), rect.height()); + } +#endif + + // Do not let the regular render queue grow past a maximum of 3 disjoint rects. + if (m_regularRenderJobsRegion.numRects() > 2) + m_regularRenderJobsRegion = Platform::unionOfRects(m_regularRenderJobsRegion.extents(), rect); + else + m_regularRenderJobsRegion = Platform::IntRectRegion::unionRegions(m_regularRenderJobsRegion, rect); + + if (!isEmpty()) + m_parent->startRenderTimer(); // Start the render timer since we could have some stale content here... +} + +void RenderQueue::addToScrollZoomQueue(const RenderRect& rect, RenderRectList* rectList) +{ + if (std::find(rectList->begin(), rectList->end(), rect) != rectList->end()) + return; + +#if DEBUG_RENDER_QUEUE + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::addToScrollZoomQueue %d,%d %dx%d", + rect.x(), rect.y(), rect.width(), rect.height()); +#endif + rectList->push_back(rect); + + if (!isEmpty()) + m_parent->startRenderTimer(); // Start the render timer since we know we could have some checkerboard here... +} + +void RenderQueue::quickSort(RenderRectList* queue) +{ + size_t length = queue->size(); + if (!length) + return; + + for (size_t i = 0; i < length; ++i) + queue->at(i).updateSortDirection(m_primarySortDirection, m_secondarySortDirection); + return std::sort(queue->begin(), queue->end(), RenderRectLessThan(m_primarySortDirection, m_secondarySortDirection)); +} + +void RenderQueue::updateSortDirection(int lastDeltaX, int lastDeltaY) +{ + bool primaryIsHorizontal = abs(lastDeltaX) >= abs(lastDeltaY); + if (primaryIsHorizontal) { + m_primarySortDirection = lastDeltaX <= 0 ? LeftToRight : RightToLeft; + m_secondarySortDirection = lastDeltaY <= 0 ? TopToBottom : BottomToTop; + } else { + m_primarySortDirection = lastDeltaY <= 0 ? TopToBottom : BottomToTop; + m_secondarySortDirection = lastDeltaX <= 0 ? LeftToRight : RightToLeft; + } +} + +void RenderQueue::visibleContentChanged(const Platform::IntRect& visibleContent) +{ + if (m_visibleScrollJobs.empty() && m_nonVisibleScrollJobs.empty()) { + ASSERT(m_visibleScrollJobsCompleted.empty() && m_nonVisibleScrollJobsCompleted.empty()); + return; + } + + // Move visibleScrollJobs to nonVisibleScrollJobs if they do not intersect + // the visible content rect. + for (size_t i = 0; i < m_visibleScrollJobs.size(); ++i) { + RenderRect rect = m_visibleScrollJobs.at(i); + if (!rect.intersects(visibleContent)) { + m_visibleScrollJobs.erase(m_visibleScrollJobs.begin() + i); + addToScrollZoomQueue(rect, &m_nonVisibleScrollJobs); + --i; + } + } + + // Do the same for the completed list. + for (size_t i = 0; i < m_visibleScrollJobsCompleted.size(); ++i) { + RenderRect rect = m_visibleScrollJobsCompleted.at(i); + if (!rect.intersects(visibleContent)) { + m_visibleScrollJobsCompleted.erase(m_visibleScrollJobsCompleted.begin() + i); + addToScrollZoomQueue(rect, &m_nonVisibleScrollJobsCompleted); + --i; + } + } + + // Move nonVisibleScrollJobs to visibleScrollJobs if they do intersect + // the visible content rect. + for (size_t i = 0; i < m_nonVisibleScrollJobs.size(); ++i) { + RenderRect rect = m_nonVisibleScrollJobs.at(i); + if (rect.intersects(visibleContent)) { + m_nonVisibleScrollJobs.erase(m_nonVisibleScrollJobs.begin() + i); + addToScrollZoomQueue(rect, &m_visibleScrollJobs); + --i; + } + } + + // Do the same for the completed list. + for (size_t i = 0; i < m_nonVisibleScrollJobsCompleted.size(); ++i) { + RenderRect rect = m_nonVisibleScrollJobsCompleted.at(i); + if (rect.intersects(visibleContent)) { + m_nonVisibleScrollJobsCompleted.erase(m_nonVisibleScrollJobsCompleted.begin() + i); + addToScrollZoomQueue(rect, &m_visibleScrollJobsCompleted); + --i; + } + } + + if (m_visibleScrollJobs.empty() && !m_visibleScrollJobsCompleted.empty()) + visibleScrollJobsCompleted(false /*shouldBlit*/); + + if (m_nonVisibleScrollJobs.empty() && !m_nonVisibleScrollJobsCompleted.empty()) + nonVisibleScrollJobsCompleted(); + + // We shouldn't be empty because the early return above and the fact that this + // method just shuffles rects from queue to queue hence the total number of + // rects in the various queues should be conserved. + ASSERT(!isEmpty()); +} + +void RenderQueue::clear(const Platform::IntRectRegion& region, bool clearRegularRenderJobs) +{ + IntRectList rects = region.rects(); + for (size_t i = 0; i < rects.size(); ++i) + clear(rects.at(i), clearRegularRenderJobs); +} + +void RenderQueue::clear(const Platform::IntRect& rect, bool clearRegularRenderJobs) +{ + if (m_visibleScrollJobs.empty() && m_nonVisibleScrollJobs.empty()) + ASSERT(m_visibleScrollJobsCompleted.empty() && m_nonVisibleScrollJobsCompleted.empty()); + + // Remove all rects from all queues that are contained by this rect. + for (size_t i = 0; i < m_visibleScrollJobs.size(); ++i) { + if (rect.contains(m_visibleScrollJobs.at(i))) { + m_visibleScrollJobs.erase(m_visibleScrollJobs.begin() + i); + --i; + } + } + + for (size_t i = 0; i < m_visibleScrollJobsCompleted.size(); ++i) { + if (rect.contains(m_visibleScrollJobsCompleted.at(i))) { + m_visibleScrollJobsCompleted.erase(m_visibleScrollJobsCompleted.begin() + i); + --i; + } + } + + for (size_t i = 0; i < m_nonVisibleScrollJobs.size(); ++i) { + if (rect.contains(m_nonVisibleScrollJobs.at(i))) { + m_nonVisibleScrollJobs.erase(m_nonVisibleScrollJobs.begin() + i); + --i; + } + } + + for (size_t i = 0; i < m_nonVisibleScrollJobsCompleted.size(); ++i) { + if (rect.contains(m_nonVisibleScrollJobsCompleted.at(i))) { + m_nonVisibleScrollJobsCompleted.erase(m_nonVisibleScrollJobsCompleted.begin() + i); + --i; + } + } + + // Only clear the regular render jobs if the flag has been set. + if (clearRegularRenderJobs) + this->clearRegularRenderJobs(rect); + + if (m_visibleScrollJobs.empty() && !m_visibleScrollJobsCompleted.empty()) + visibleScrollJobsCompleted(false /*shouldBlit*/); + + if (m_nonVisibleScrollJobs.empty() && !m_nonVisibleScrollJobsCompleted.empty()) + nonVisibleScrollJobsCompleted(); + + if (isEmpty()) + m_parent->stopRenderTimer(); +} + +void RenderQueue::clearRegularRenderJobs(const Platform::IntRect& rect) +{ + for (size_t i = 0; i < m_currentRegularRenderJobsBatch.size(); ++i) { + if (rect.contains(m_currentRegularRenderJobsBatch.at(i))) { + m_currentRegularRenderJobsBatch.erase(m_currentRegularRenderJobsBatch.begin() + i); + --i; + } + } + m_regularRenderJobsRegion = Platform::IntRectRegion::subtractRegions(m_regularRenderJobsRegion, rect); + m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion::subtractRegions(m_currentRegularRenderJobsBatchRegion, rect); + m_regularRenderJobsNotRenderedRegion = Platform::IntRectRegion::subtractRegions(m_regularRenderJobsNotRenderedRegion, rect); +} + +void RenderQueue::clearVisibleZoom() +{ + m_visibleZoomJobs.clear(); + if (isEmpty()) + m_parent->stopRenderTimer(); +} + +bool RenderQueue::regularRenderJobsPreviouslyAttemptedButNotRendered(const Platform::IntRect& rect) +{ + return m_regularRenderJobsNotRenderedRegion.isRectInRegion(rect) != Platform::IntRectRegion::NotInRegion; +} + +void RenderQueue::render(bool shouldPerformRegularRenderJobs) +{ + // We request a layout here to ensure that we're executing jobs in the correct + // order. If we didn't request a layout here then the jobs below could result + // in a layout and that layout can alter this queue. So request layout if needed + // to ensure that the queues below are in constant state before performing the + // next rendering job. + +#if DEBUG_RENDER_QUEUE + // Start the time measurement. + double time = WTF::currentTime(); +#endif + + m_parent->requestLayoutIfNeeded(); + +#if DEBUG_RENDER_QUEUE + double elapsed = WTF::currentTime() - time; + if (elapsed) + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::render layout elapsed=%f", elapsed); +#endif + + // Empty the queues in a precise order of priority. + if (!m_visibleZoomJobs.empty()) + renderVisibleZoomJob(); + else if (!m_visibleScrollJobs.empty()) + renderVisibleScrollJob(); + else if (shouldPerformRegularRenderJobs && (!m_currentRegularRenderJobsBatch.empty() || !m_regularRenderJobsRegion.isEmpty())) { + if (currentRegularRenderJobBatchUnderPressure()) + renderAllCurrentRegularRenderJobs(); + else + renderRegularRenderJob(); + } else if (!m_nonVisibleScrollJobs.empty()) + renderNonVisibleScrollJob(); + + if (isEmpty()) + m_parent->stopRenderTimer(); +} + +void RenderQueue::renderAllCurrentRegularRenderJobs() +{ +#if DEBUG_RENDER_QUEUE + // Start the time measurement... + double time = WTF::currentTime(); +#endif + + // Request layout first + m_parent->requestLayoutIfNeeded(); + +#if DEBUG_RENDER_QUEUE + double elapsed = WTF::currentTime() - time; + if (elapsed) + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderAllCurrentRegularRenderJobs layout elapsed=%f", elapsed); +#endif + + // The state of render queue may be modified from inside requestLayoutIfNeeded. + // In fact, it can even be emptied entirely! Layout can trigger a call to + // RenderQueue::clear. See PR#101811 for instance. So we should check again here. + if (!hasCurrentRegularRenderJob()) + return; + + // If there is no current batch of jobs, then create one. + if (m_currentRegularRenderJobsBatchRegion.isEmpty()) { + + // Create a current region object from our regular render region. + m_currentRegularRenderJobsBatchRegion = m_regularRenderJobsRegion; + + // Clear this since we're about to render everything. + m_regularRenderJobsRegion = Platform::IntRectRegion(); + } + + Platform::IntRectRegion regionNotRendered; + if (m_parent->shouldSuppressNonVisibleRegularRenderJobs()) { + // Record any part of the region that doesn't intersect the current visible contents rect. + regionNotRendered = Platform::IntRectRegion::subtractRegions(m_currentRegularRenderJobsBatchRegion, m_parent->visibleContentsRect()); + m_regularRenderJobsNotRenderedRegion = Platform::IntRectRegion::unionRegions(m_regularRenderJobsNotRenderedRegion, regionNotRendered); + +#if DEBUG_RENDER_QUEUE + if (!regionNotRendered.isEmpty()) + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderAllCurrentRegularRenderJobs region not completely rendered!"); +#endif + + // Clip to the visible contents so we'll be faster. + m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion::intersectRegions(m_currentRegularRenderJobsBatchRegion, m_parent->visibleContentsRect()); + } + + bool rendered = false; + if (!m_currentRegularRenderJobsBatchRegion.isEmpty()) { + std::vector<Platform::IntRect> rectList = m_currentRegularRenderJobsBatchRegion.rects(); + for (size_t i = 0; i < rectList.size(); ++i) + rendered = m_parent->render(rectList.at(i)) ? true : rendered; + } + +#if DEBUG_RENDER_QUEUE + // Stop the time measurement. + elapsed = WTF::currentTime() - time; + Platform::IntRect extents = m_currentRegularRenderJobsBatchRegion.extents(); + int numberOfRects = m_currentRegularRenderJobsBatchRegion.rects().size(); + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderAllCurrentRegularRenderJobs extents=(%d,%d %dx%d) numberOfRects=%d elapsed=%f", + extents.x(), extents.y(), extents.width(), extents.height(), numberOfRects, elapsed); +#endif + + // Clear the region and blit since this batch is now complete. + Platform::IntRect renderedRect = m_currentRegularRenderJobsBatchRegion.extents(); + m_currentRegularRenderJobsBatch.clear(); + m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion(); + m_currentRegularRenderJobsBatchUnderPressure = false; + + // Update the screen only if we're not scrolling or zooming. + if (rendered && !m_parent->isScrollingOrZooming()) { + if (!m_parent->shouldDirectRenderingToWindow()) + m_parent->blitVisibleContents(); + else + m_parent->invalidateWindow(); + m_parent->m_webPage->client()->notifyContentRendered(renderedRect); + } + + if (m_parent->shouldSuppressNonVisibleRegularRenderJobs() && !regionNotRendered.isEmpty()) + m_parent->updateTilesForScrollOrNotRenderedRegion(false /*checkLoading*/); +} + +void RenderQueue::startRegularRenderJobBatchIfNeeded() +{ + if (!m_currentRegularRenderJobsBatch.empty()) + return; + + // Decompose the current regular render job region into render rect pieces. + IntRectList regularRenderJobs = m_regularRenderJobsRegion.rects(); + + // The current batch... + m_currentRegularRenderJobsBatch = regularRenderJobs; + + // Create a region object that will be checked when adding new rects before + // this batch has been completed. + m_currentRegularRenderJobsBatchRegion = m_regularRenderJobsRegion; + + // Clear the former region since it is now part of this batch. + m_regularRenderJobsRegion = Platform::IntRectRegion(); + +#if DEBUG_RENDER_QUEUE + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::startRegularRenderJobBatchIfNeeded batch size is %d!", m_currentRegularRenderJobsBatch.size()); +#endif +} + +void RenderQueue::renderVisibleZoomJob() +{ + ASSERT(m_visibleZoomJobs.size() > 0); + +#if DEBUG_RENDER_QUEUE + // Start the time measurement. + double time = WTF::currentTime(); +#endif + + RenderRect* rect = &m_visibleZoomJobs[0]; + ASSERT(!rect->isCompleted()); + Platform::IntRect subRect = rect->rectForRendering(); + if (rect->isCompleted()) + m_visibleZoomJobs.erase(m_visibleZoomJobs.begin()); + + m_parent->render(subRect); + + // Record that it has now been rendered via a different type of job... + clearRegularRenderJobs(subRect); + +#if DEBUG_RENDER_QUEUE + // Stop the time measurement + double elapsed = WTF::currentTime() - time; + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderVisibleZoomJob rect=(%d,%d %dx%d) elapsed=%f", + subRect.x(), subRect.y(), subRect.width(), subRect.height(), elapsed); +#endif +} + +void RenderQueue::renderVisibleScrollJob() +{ + ASSERT(!m_visibleScrollJobs.empty()); + +#if DEBUG_RENDER_QUEUE || DEBUG_RENDER_QUEUE_SORT + // Start the time measurement. + double time = WTF::currentTime(); +#endif + + quickSort(&m_visibleScrollJobs); + +#if DEBUG_RENDER_QUEUE_SORT + // Stop the time measurement + double elapsed = WTF::currentTime() - time; + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderVisibleScrollJob sort elapsed=%f", elapsed); +#endif + + RenderRect rect = m_visibleScrollJobs[0]; + m_visibleScrollJobs.erase(m_visibleScrollJobs.begin()); + + ASSERT(!rect.isCompleted()); + Platform::IntRect subRect = rect.rectForRendering(); + if (rect.isCompleted()) + m_visibleScrollJobsCompleted.push_back(rect); + else + m_visibleScrollJobs.insert(m_visibleScrollJobs.begin(), rect); + + m_parent->render(subRect); + + // Record that it has now been rendered via a different type of job... + clearRegularRenderJobs(subRect); + +#if DEBUG_RENDER_QUEUE + // Stop the time measurement + double elapsed = WTF::currentTime() - time; + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderVisibleScrollJob rect=(%d,%d %dx%d) elapsed=%f", + subRect.x(), subRect.y(), subRect.width(), subRect.height(), elapsed); +#endif + + if (m_visibleScrollJobs.empty()) + visibleScrollJobsCompleted(true /*shouldBlit*/); +} + +void RenderQueue::renderRegularRenderJob() +{ +#if DEBUG_RENDER_QUEUE + // Start the time measurement. + double time = WTF::currentTime(); +#endif + + ASSERT(!m_currentRegularRenderJobsBatch.empty() || !m_regularRenderJobsRegion.isEmpty()); + + startRegularRenderJobBatchIfNeeded(); + + // Take the first job from the regular render job queue. + Platform::IntRect rect = m_currentRegularRenderJobsBatch[0]; + m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion::subtractRegions(m_currentRegularRenderJobsBatchRegion, Platform::IntRectRegion(rect)); + m_currentRegularRenderJobsBatch.erase(m_currentRegularRenderJobsBatch.begin()); + + Platform::IntRectRegion regionNotRendered; + if (m_parent->shouldSuppressNonVisibleRegularRenderJobs()) { + // Record any part of the region that doesn't intersect the current visible tiles rect. + regionNotRendered = Platform::IntRectRegion::subtractRegions(rect, m_parent->visibleContentsRect()); + m_regularRenderJobsNotRenderedRegion = Platform::IntRectRegion::unionRegions(m_regularRenderJobsNotRenderedRegion, regionNotRendered); + +#if DEBUG_RENDER_QUEUE + if (!regionNotRendered.isEmpty()) { + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderRegularRenderJob rect (%d,%d %dx%d) not completely rendered!", + rect.x(), rect.y(), rect.width(), rect.height()); + } +#endif + + // Clip to the visible tiles so we'll be faster. + rect.intersect(m_parent->visibleContentsRect()); + } + + if (!rect.isEmpty()) + m_parent->render(rect); + +#if DEBUG_RENDER_QUEUE + // Stop the time measurement. + double elapsed = WTF::currentTime() - time; + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderRegularRenderJob rect=(%d,%d %dx%d) elapsed=%f", + rect.x(), rect.y(), rect.width(), rect.height(), elapsed); +#endif + + if (m_currentRegularRenderJobsBatch.empty()) { + Platform::IntRect renderedRect = m_currentRegularRenderJobsBatchRegion.extents(); + // Clear the region and the and blit since this batch is now complete. + m_currentRegularRenderJobsBatchRegion = Platform::IntRectRegion(); + m_currentRegularRenderJobsBatchUnderPressure = false; + // Update the screen only if we're not scrolling or zooming. + if (!m_parent->isScrollingOrZooming()) { + if (!m_parent->shouldDirectRenderingToWindow()) + m_parent->blitVisibleContents(); + else + m_parent->invalidateWindow(); + m_parent->m_webPage->client()->notifyContentRendered(renderedRect); + } + } + + // Make sure we didn't alter state of the queues that should have been empty + // before this method was called. + ASSERT(m_visibleScrollJobs.empty()); + + if (m_parent->shouldSuppressNonVisibleRegularRenderJobs() && !regionNotRendered.isEmpty()) + m_parent->updateTilesForScrollOrNotRenderedRegion(false /*checkLoading*/); +} + +void RenderQueue::renderNonVisibleScrollJob() +{ + ASSERT(!m_nonVisibleScrollJobs.empty()); + +#if DEBUG_RENDER_QUEUE || DEBUG_RENDER_QUEUE_SORT + // Start the time measurement. + double time = WTF::currentTime(); +#endif + + quickSort(&m_nonVisibleScrollJobs); + +#if DEBUG_RENDER_QUEUE_SORT + // Stop the time measurement. + double elapsed = WTF::currentTime() - time; + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderNonVisibleScrollJob sort elapsed=%f", elapsed); +#endif + + RenderRect rect = m_nonVisibleScrollJobs[0]; + m_nonVisibleScrollJobs.erase(m_nonVisibleScrollJobs.begin()); + + ASSERT(!rect.isCompleted()); + Platform::IntRect subRect = rect.rectForRendering(); + if (rect.isCompleted()) + m_nonVisibleScrollJobsCompleted.push_back(rect); + else + m_nonVisibleScrollJobs.insert(m_nonVisibleScrollJobs.begin(), rect); + + m_parent->render(subRect); + + // Record that it has now been rendered via a different type of job... + clearRegularRenderJobs(subRect); + + // Make sure we didn't alter state of the queues that should have been empty + // before this method was called. + ASSERT(m_visibleScrollJobs.empty()); + +#if DEBUG_RENDER_QUEUE + // Stop the time measurement. + double elapsed = WTF::currentTime() - time; + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "RenderQueue::renderNonVisibleScrollJob rect=(%d,%d %dx%d) elapsed=%f", + subRect.x(), subRect.y(), subRect.width(), subRect.height(), elapsed); +#endif + + if (m_nonVisibleScrollJobs.empty()) + nonVisibleScrollJobsCompleted(); +} + +void RenderQueue::visibleScrollJobsCompleted(bool shouldBlit) +{ + // Now blit to the screen if we are done and get rid of the completed list! + ASSERT(m_visibleScrollJobs.empty()); + m_visibleScrollJobsCompleted.clear(); + if (shouldBlit && !m_parent->isScrollingOrZooming()) { + if (!m_parent->shouldDirectRenderingToWindow()) + m_parent->blitVisibleContents(); + else + m_parent->invalidateWindow(); + m_parent->m_webPage->client()->notifyContentRendered(m_parent->visibleContentsRect()); + } +} + +void RenderQueue::nonVisibleScrollJobsCompleted() +{ + // Get rid of the completed list! + ASSERT(m_nonVisibleScrollJobs.empty()); + m_nonVisibleScrollJobsCompleted.clear(); +} + +} // namespace WebKit +} // namespace BlackBerry diff --git a/Source/WebKit/blackberry/WebKitSupport/RenderQueue.h b/Source/WebKit/blackberry/WebKitSupport/RenderQueue.h new file mode 100644 index 000000000..3c9639e67 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/RenderQueue.h @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RenderQueue_h +#define RenderQueue_h + +#include <BlackBerryPlatformIntRectRegion.h> +#include <BlackBerryPlatformPrimitives.h> +#include <vector> + +namespace BlackBerry { +namespace WebKit { + +class BackingStorePrivate; + +typedef std::vector<Platform::IntRect> IntRectList; + +enum SortDirection { + LeftToRight = 0, + RightToLeft, + TopToBottom, + BottomToTop, + NumSortDirections +}; + +class RenderRect : public Platform::IntRect { +public: + RenderRect() { } + RenderRect(const Platform::IntPoint& location, const Platform::IntSize&, int splittingFactor); + RenderRect(int x, int y, int width, int height, int splittingFactor); + RenderRect(const Platform::IntRect&); + + Platform::IntRect rectForRendering(); + + bool isCompleted() const { return !m_subRects.size(); } + + const IntRectList& subRects() const { return m_subRects; } + void updateSortDirection(SortDirection primary, SortDirection secondary); + +private: + void initialize(int splittingFactor); + void split(); + void quickSort(); + int m_splittingFactor; + IntRectList m_subRects; + SortDirection m_primarySortDirection; + SortDirection m_secondarySortDirection; +}; + +typedef std::vector<RenderRect> RenderRectList; + +class RenderQueue { +public: + enum JobType { VisibleZoom, VisibleScroll, RegularRender, NonVisibleScroll }; + RenderQueue(BackingStorePrivate*); + + void reset(); + RenderRect convertToRenderRect(const Platform::IntRect&) const; + + bool isEmpty(bool shouldPerformRegularRenderJobs = true) const; + + bool hasCurrentRegularRenderJob() const; + bool hasCurrentVisibleZoomJob() const; + bool hasCurrentVisibleScrollJob() const; + bool isCurrentVisibleScrollJob(const Platform::IntRect&) const; + bool isCurrentVisibleScrollJobCompleted(const Platform::IntRect&) const; + bool isCurrentRegularRenderJob(const Platform::IntRect&) const; + + bool currentRegularRenderJobBatchUnderPressure() const; + void setCurrentRegularRenderJobBatchUnderPressure(bool); + + void eventQueueCycled(); + + void addToQueue(JobType, const Platform::IntRect&); + void addToQueue(JobType, const IntRectList&); + + void updateSortDirection(int lastDeltaX, int lastDeltaY); + void visibleContentChanged(const Platform::IntRect&); + void clear(const Platform::IntRectRegion&, bool clearRegularRenderJobs); + void clear(const Platform::IntRect&, bool clearRegularRenderJobs); + void clearRegularRenderJobs(const Platform::IntRect&); + void clearVisibleZoom(); + bool regularRenderJobsPreviouslyAttemptedButNotRendered(const Platform::IntRect&); + Platform::IntRectRegion regularRenderJobsNotRenderedRegion() const { return m_regularRenderJobsNotRenderedRegion; } + + void render(bool shouldPerformRegularRenderJobs = true); + void renderAllCurrentRegularRenderJobs(); + +private: + void startRegularRenderJobBatchIfNeeded(); + + // Render an item from the queue. + void renderVisibleZoomJob(); + void renderVisibleScrollJob(); + void renderRegularRenderJob(); + void renderNonVisibleScrollJob(); + + // Methods to handle a completed set of scroll jobs. + void visibleScrollJobsCompleted(bool shouldBlit); + void nonVisibleScrollJobsCompleted(); + + // Internal method to add to the various queues. + void addToRegularQueue(const Platform::IntRect&); + void addToScrollZoomQueue(const RenderRect&, RenderRectList* queue); + void quickSort(RenderRectList*); + + // The splitting factor for render rects. + int splittingFactor(const Platform::IntRect&) const; + + BackingStorePrivate* m_parent; + + // The highest priority queue. + RenderRectList m_visibleZoomJobs; + RenderRectList m_visibleScrollJobs; + RenderRectList m_visibleScrollJobsCompleted; + // The lowest priority queue. + RenderRectList m_nonVisibleScrollJobs; + RenderRectList m_nonVisibleScrollJobsCompleted; + // The regular render jobs are in the middle. + Platform::IntRectRegion m_regularRenderJobsRegion; + IntRectList m_currentRegularRenderJobsBatch; + Platform::IntRectRegion m_currentRegularRenderJobsBatchRegion; + bool m_rectsAddedToRegularRenderJobsInCurrentCycle; + bool m_currentRegularRenderJobsBatchUnderPressure; + + // Holds the region of the page that we attempt to render, but the + // backingstore was not in the right place at the time. This will + // be checked before we try to restore a tile to it's last rendered + // place. + Platform::IntRectRegion m_regularRenderJobsNotRenderedRegion; + + SortDirection m_primarySortDirection; + SortDirection m_secondarySortDirection; +}; + +} // namespace WebKit +} // namespace BlackBerry + +#endif // RenderQueue_h diff --git a/Source/WebKit/blackberry/WebKitSupport/SelectionHandler.cpp b/Source/WebKit/blackberry/WebKitSupport/SelectionHandler.cpp new file mode 100644 index 000000000..0723c65c8 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/SelectionHandler.cpp @@ -0,0 +1,943 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "SelectionHandler.h" + +#include "DOMSupport.h" +#include "Document.h" +#include "Editor.h" +#include "EditorClient.h" +#include "FatFingers.h" +#include "Frame.h" +#include "FrameSelection.h" +#include "FrameView.h" +#include "HTMLAnchorElement.h" +#include "HTMLAreaElement.h" +#include "HitTestResult.h" +#include "InputHandler.h" +#include "IntRect.h" +#include "Page.h" +#include "RenderPart.h" +#include "TextGranularity.h" +#include "TouchEventHandler.h" +#include "WebPage.h" +#include "WebPageClient.h" +#include "WebPage_p.h" + +#include "htmlediting.h" +#include "visible_units.h" + +#include <BlackBerryPlatformKeyboardEvent.h> + +#include <sys/keycodes.h> + +#define SHOWDEBUG_SELECTIONHANDLER 0 + +#if SHOWDEBUG_SELECTIONHANDLER +#define DEBUG_SELECTION(severity, format, ...) BlackBerry::Platform::logAlways(severity, format, ## __VA_ARGS__) +#else +#define DEBUG_SELECTION(severity, format, ...) +#endif // SHOWDEBUG_SELECTIONHANDLER + +using namespace WebCore; + +namespace BlackBerry { +namespace WebKit { + +SelectionHandler::SelectionHandler(WebPagePrivate* page) + : m_webPage(page) + , m_selectionActive(false) + , m_caretActive(false) + , m_lastUpdatedEndPointIsValid(false) +{ +} + +SelectionHandler::~SelectionHandler() +{ +} + +void SelectionHandler::cancelSelection() +{ + m_selectionActive = false; + m_lastSelectionRegion = BlackBerry::Platform::IntRectRegion(); + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::cancelSelection"); + + if (m_webPage->m_inputHandler->isInputMode()) + m_webPage->m_inputHandler->cancelSelection(); + else + m_webPage->focusedOrMainFrame()->selection()->clear(); +} + +WebString SelectionHandler::selectedText() const +{ + return m_webPage->focusedOrMainFrame()->editor()->selectedText(); +} + +void SelectionHandler::getConsolidatedRegionOfTextQuadsForSelection(const VisibleSelection& selection, BlackBerry::Platform::IntRectRegion& region) const +{ + ASSERT(region.isEmpty()); + + if (!selection.isRange()) + return; + + ASSERT(selection.firstRange()); + + Vector<FloatQuad> quadList; + DOMSupport::visibleTextQuads(*(selection.firstRange()), quadList, true /* use selection height */); + + if (!quadList.isEmpty()) { + FrameView* frameView = m_webPage->focusedOrMainFrame()->view(); + + // frameRect is in frame coordinates. + IntRect frameRect(IntPoint(0, 0), frameView->contentsSize()); + + // framePosition is in main frame coordinates. + IntPoint framePosition = m_webPage->frameOffset(m_webPage->focusedOrMainFrame()); + + // The ranges rect list is based on render elements and may include multiple adjacent rects. + // Use BlackBerry::Platform::IntRectRegion to consolidate these rects into bands as well as a container to pass + // to the client. + for (unsigned i = 0; i < quadList.size(); i++) { + IntRect enclosingRect = quadList[i].enclosingBoundingBox(); + enclosingRect.intersect(frameRect); + enclosingRect.move(framePosition.x(), framePosition.y()); + region = unionRegions(region, BlackBerry::Platform::IntRectRegion(enclosingRect)); + } + } +} + +static VisiblePosition visiblePositionForPointIgnoringClipping(const Frame& frame, const IntPoint& framePoint) +{ + // Frame::visiblePositionAtPoint hard-codes ignoreClipping=false in the + // call to hitTestResultAtPoint. This has a bug where some pages (such as + // metafilter) will return the wrong VisiblePosition for points that are + // outside the visible rect. To work around the bug, this is a copy of + // visiblePositionAtPoint which which passes ignoreClipping=true. + // See RIM Bug #4315. + HitTestResult result = frame.eventHandler()->hitTestResultAtPoint(framePoint, true /* allowShadowContent */, true /* ignoreClipping */); + + Node* node = result.innerNode(); + if (!node) + return VisiblePosition(); + + RenderObject* renderer = node->renderer(); + if (!renderer) + return VisiblePosition(); + + VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint()); + if (visiblePos.isNull()) + visiblePos = VisiblePosition(Position(createLegacyEditingPosition(node, 0))); + + return visiblePos; +} + +static unsigned short directionOfPointRelativeToRect(const IntPoint& point, const IntRect& rect, const bool useTopPadding = true, const bool useBottomPadding = true) +{ + ASSERT(!rect.contains(point)); + + // Padding to prevent accidental trigger of up/down when intending to do horizontal movement. + const int verticalPadding = 5; + + // Do height movement check first but add padding. We may be off on both x & y axis and only + // want to move in one direction at a time. + if (point.y() + (useTopPadding ? verticalPadding : 0) < rect.y()) + return KEYCODE_UP; + if (point.y() > rect.maxY() + (useBottomPadding ? verticalPadding : 0)) + return KEYCODE_DOWN; + if (point.x() < rect.location().x()) + return KEYCODE_LEFT; + if (point.x() > rect.maxX()) + return KEYCODE_RIGHT; + + return 0; +} + +bool SelectionHandler::shouldUpdateSelectionOrCaretForPoint(const IntPoint& point, const IntRect& caretRect, bool startCaret) const +{ + ASSERT(m_webPage->m_inputHandler->isInputMode()); + + // If the point isn't valid don't block change as it is not actually changing. + if (point == DOMSupport::InvalidPoint) + return true; + + VisibleSelection currentSelection = m_webPage->focusedOrMainFrame()->selection()->selection(); + + // If the input field is single line or we are on the first or last + // line of a multiline input field only horizontal movement is supported. + bool aboveCaret = point.y() < caretRect.y(); + bool belowCaret = point.y() >= caretRect.maxY(); + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::shouldUpdateSelectionOrCaretForPoint multiline = %s above = %s below = %s first line = %s last line = %s start = %s \n" + , m_webPage->m_inputHandler->isMultilineInputMode() ? "true" : "false", aboveCaret ? "true" : "false", belowCaret ? "true" : "false" + , inSameLine(currentSelection.visibleStart(), startOfEditableContent(currentSelection.visibleStart())) ? "true" : "false" + , inSameLine(currentSelection.visibleEnd(), endOfEditableContent(currentSelection.visibleEnd())) ? "true" : "false" + , startCaret ? "true" : "false"); + + if (!m_webPage->m_inputHandler->isMultilineInputMode() && (aboveCaret || belowCaret)) + return false; + if (startCaret && inSameLine(currentSelection.visibleStart(), startOfEditableContent(currentSelection.visibleStart())) && aboveCaret) + return false; + if (!startCaret && inSameLine(currentSelection.visibleEnd(), endOfEditableContent(currentSelection.visibleEnd())) && belowCaret) + return false; + + return true; +} + +void SelectionHandler::setCaretPosition(const IntPoint &position) +{ + if (!m_webPage->m_inputHandler->isInputMode()) + return; + + m_caretActive = true; + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::setCaretPosition requested point %d, %d", position.x(), position.y()); + + Frame* focusedFrame = m_webPage->focusedOrMainFrame(); + FrameSelection* controller = focusedFrame->selection(); + IntPoint relativePoint = DOMSupport::convertPointToFrame(m_webPage->mainFrame(), focusedFrame, position); + IntRect currentCaretRect = controller->selection().visibleStart().absoluteCaretBounds(); + + if (relativePoint == DOMSupport::InvalidPoint || !shouldUpdateSelectionOrCaretForPoint(relativePoint, currentCaretRect)) { + selectionPositionChanged(); + return; + } + + VisiblePosition visibleCaretPosition(focusedFrame->visiblePositionForPoint(relativePoint)); + + if (!DOMSupport::isPositionInNode(m_webPage->focusedOrMainFrame()->document()->focusedNode(), visibleCaretPosition.deepEquivalent())) { + if (unsigned short character = directionOfPointRelativeToRect(relativePoint, currentCaretRect)) + m_webPage->m_inputHandler->handleKeyboardInput(BlackBerry::Platform::KeyboardEvent(character)); + + selectionPositionChanged(); + return; + } + + VisibleSelection newSelection(visibleCaretPosition); + if (controller->selection() == newSelection) { + selectionPositionChanged(); + return; + } + + controller->setSelection(newSelection); + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::setCaretPosition point valid, cursor updated"); +} + +// This function makes sure we are not reducing the selection to a caret selection. +static bool shouldExtendSelectionInDirection(const VisibleSelection& selection, unsigned short character) +{ + FrameSelection tempSelection; + tempSelection.setSelection(selection); + switch (character) { + case KEYCODE_LEFT: + tempSelection.modify(FrameSelection::AlterationExtend, DirectionLeft, CharacterGranularity); + break; + case KEYCODE_RIGHT: + tempSelection.modify(FrameSelection::AlterationExtend, DirectionRight, CharacterGranularity); + break; + case KEYCODE_UP: + tempSelection.modify(FrameSelection::AlterationExtend, DirectionBackward, LineGranularity); + break; + case KEYCODE_DOWN: + tempSelection.modify(FrameSelection::AlterationExtend, DirectionForward, LineGranularity); + break; + default: + break; + } + + if ((character == KEYCODE_LEFT || character == KEYCODE_RIGHT) + && (!inSameLine(selection.visibleStart(), tempSelection.selection().visibleStart()) + || !inSameLine(selection.visibleEnd(), tempSelection.selection().visibleEnd()))) + return false; + + return tempSelection.selection().selectionType() == VisibleSelection::RangeSelection; +} + +static VisiblePosition directionalVisiblePositionAtExtentOfBox(Frame* frame, const IntRect& boundingBox, unsigned short direction, const IntPoint& basePoint) +{ + ASSERT(frame); + + if (!frame) + return VisiblePosition(); + + switch (direction) { + case KEYCODE_LEFT: + // Extend x to start without modifying y. + return frame->visiblePositionForPoint(IntPoint(boundingBox.x(), basePoint.y())); + case KEYCODE_RIGHT: + // Extend x to end without modifying y. + return frame->visiblePositionForPoint(IntPoint(boundingBox.maxX(), basePoint.y())); + case KEYCODE_UP: + // Extend y to top without modifying x. + return frame->visiblePositionForPoint(IntPoint(basePoint.x(), boundingBox.y())); + case KEYCODE_DOWN: + // Extend y to bottom without modifying x. + return frame->visiblePositionForPoint(IntPoint(basePoint.x(), boundingBox.maxY())); + default: + break; + } + + return frame->visiblePositionForPoint(IntPoint(basePoint.x(), basePoint.y())); +} + +static bool pointIsOutsideOfBoundingBoxInDirection(unsigned direction, const IntPoint& selectionPoint, const IntRect& boundingBox) +{ + if ((direction == KEYCODE_LEFT && selectionPoint.x() < boundingBox.x()) + || (direction == KEYCODE_UP && selectionPoint.y() < boundingBox.y()) + || (direction == KEYCODE_RIGHT && selectionPoint.x() > boundingBox.maxX()) + || (direction == KEYCODE_DOWN && selectionPoint.y() > boundingBox.maxY())) + return true; + + return false; +} + +unsigned short SelectionHandler::extendSelectionToFieldBoundary(bool isStartHandle, const IntPoint& selectionPoint, VisibleSelection& newSelection) +{ + Frame* focusedFrame = m_webPage->focusedOrMainFrame(); + if (!focusedFrame->document()->focusedNode() || !focusedFrame->document()->focusedNode()->renderer()) + return 0; + + FrameSelection* controller = focusedFrame->selection(); + + IntRect caretRect = isStartHandle ? controller->selection().visibleStart().absoluteCaretBounds() + : controller->selection().visibleEnd().absoluteCaretBounds(); + + IntRect nodeBoundingBox = focusedFrame->document()->focusedNode()->renderer()->absoluteBoundingBoxRect(); + nodeBoundingBox.inflate(-1); + + // Start handle is outside of the field. Treat it as the changed handle and move + // relative to the start caret rect. + unsigned short character = directionOfPointRelativeToRect(selectionPoint, caretRect, isStartHandle /*useTopPadding*/, !isStartHandle /*useBottomPadding*/); + + // Prevent incorrect movement, handles can only extend the selection this way + // to prevent inversion of the handles. + if (isStartHandle && (character == KEYCODE_RIGHT || character == KEYCODE_DOWN) + || !isStartHandle && (character == KEYCODE_LEFT || character == KEYCODE_UP)) + character = 0; + + VisiblePosition newVisiblePosition = isStartHandle ? controller->selection().extent() : controller->selection().base(); + // Extend the selection to the bounds of the box before doing incremental scroll if the point is outside the node. + // Don't extend selection and handle the character at the same time. + if (pointIsOutsideOfBoundingBoxInDirection(character, selectionPoint, nodeBoundingBox)) + newVisiblePosition = directionalVisiblePositionAtExtentOfBox(focusedFrame, nodeBoundingBox, character, selectionPoint); + + if (isStartHandle) + newSelection = VisibleSelection(newVisiblePosition, newSelection.extent(), true /*isDirectional*/); + else + newSelection = VisibleSelection(newSelection.base(), newVisiblePosition, true /*isDirectional*/); + + // If no selection will be changed, return the character to extend using navigation. + if (controller->selection() == newSelection) + return character; + + // Selection has been updated. + return 0; +} + +// Returns true if handled. +bool SelectionHandler::updateOrHandleInputSelection(VisibleSelection& newSelection, const IntPoint& relativeStart + , const IntPoint& relativeEnd) +{ + ASSERT(m_webPage->m_inputHandler->isInputMode()); + + Frame* focusedFrame = m_webPage->focusedOrMainFrame(); + Node* focusedNode = focusedFrame->document()->focusedNode(); + if (!focusedNode || !focusedNode->renderer()) + return false; + + FrameSelection* controller = focusedFrame->selection(); + + IntRect currentStartCaretRect = controller->selection().visibleStart().absoluteCaretBounds(); + IntRect currentEndCaretRect = controller->selection().visibleEnd().absoluteCaretBounds(); + + // Check if the handle movement is valid. + if (!shouldUpdateSelectionOrCaretForPoint(relativeStart, currentStartCaretRect, true /* startCaret */) + || !shouldUpdateSelectionOrCaretForPoint(relativeEnd, currentEndCaretRect, false /* startCaret */)) { + selectionPositionChanged(); + return true; + } + + IntRect nodeBoundingBox = focusedNode->renderer()->absoluteBoundingBoxRect(); + + // Only do special handling if one handle is outside of the node. + bool startIsOutsideOfField = relativeStart != DOMSupport::InvalidPoint && !nodeBoundingBox.contains(relativeStart); + bool endIsOutsideOfField = relativeEnd != DOMSupport::InvalidPoint && !nodeBoundingBox.contains(relativeEnd); + if (startIsOutsideOfField && endIsOutsideOfField) + return false; + + unsigned short character = 0; + if (startIsOutsideOfField) { + character = extendSelectionToFieldBoundary(true /* isStartHandle */, relativeStart, newSelection); + if (character) { + // Invert the selection so that the cursor point is at the beginning. + controller->setSelection(VisibleSelection(controller->selection().end(), controller->selection().start())); + } + } else if (endIsOutsideOfField) { + character = extendSelectionToFieldBoundary(false /* isStartHandle */, relativeEnd, newSelection); + if (character) { + // Reset the selection so that the end is the edit point. + controller->setSelection(VisibleSelection(controller->selection().start(), controller->selection().end())); + } + } + + if (!character) + return false; + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::setSelection making selection change attempt using key event %d", character); + + if (shouldExtendSelectionInDirection(controller->selection(), character)) + m_webPage->m_inputHandler->handleKeyboardInput(BlackBerry::Platform::KeyboardEvent(character, BlackBerry::Platform::KeyboardEvent::KeyDown, KEYMOD_SHIFT)); + + // Must send the selectionPositionChanged every time, sometimes this will duplicate but an accepted + // handleNavigationMove may not make an actual selection change. + selectionPositionChanged(); + return true; +} + +IntPoint SelectionHandler::clipPointToFocusNode(const IntPoint& point) +{ + Frame* focusedFrame = m_webPage->focusedOrMainFrame(); + FrameSelection* controller = focusedFrame->selection(); + + if (!focusedFrame->document()->focusedNode() || !focusedFrame->document()->focusedNode()->renderer()) + return point; + + IntRect focusedNodeBoundingBox = focusedFrame->document()->focusedNode()->renderer()->absoluteBoundingBoxRect(); + focusedNodeBoundingBox.inflate(-1); + + IntPoint clippedPoint = point; + if (!focusedNodeBoundingBox.contains(clippedPoint)) + clippedPoint = IntPoint( + point.x() < focusedNodeBoundingBox.x() ? focusedNodeBoundingBox.x() : std::min(focusedNodeBoundingBox.maxX(), point.x()), + point.y() < focusedNodeBoundingBox.y() ? focusedNodeBoundingBox.y() : std::min(focusedNodeBoundingBox.maxY(), point.y())); + + return clippedPoint; +} + +void SelectionHandler::setSelection(const IntPoint& start, const IntPoint& end) +{ + m_selectionActive = true; + + ASSERT(m_webPage); + ASSERT(m_webPage->focusedOrMainFrame()); + ASSERT(m_webPage->focusedOrMainFrame()->selection()); + + Frame* focusedFrame = m_webPage->focusedOrMainFrame(); + FrameSelection* controller = focusedFrame->selection(); + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::setSelection adjusted points %d, %d, %d, %d", start.x(), start.y(), end.x(), end.y()); + + // Note that IntPoint(-1, -1) is being our sentinel so far for + // clipped out selection starting or ending location. + bool startIsValid = start != DOMSupport::InvalidPoint; + m_lastUpdatedEndPointIsValid = end != DOMSupport::InvalidPoint; + + // At least one of the locations must be valid. + ASSERT(startIsValid || m_lastUpdatedEndPointIsValid); + + IntPoint relativeStart = start; + IntPoint relativeEnd = end; + + VisibleSelection newSelection(controller->selection()); + + // We need the selection to be ordered base then extent. + if (!controller->selection().isBaseFirst()) + controller->setSelection(VisibleSelection(controller->selection().start(), controller->selection().end())); + + if (startIsValid) { + relativeStart = DOMSupport::convertPointToFrame(m_webPage->mainFrame(), focusedFrame, start); + + // Set the selection with validation. + newSelection.setBase(visiblePositionForPointIgnoringClipping(*focusedFrame, clipPointToFocusNode(relativeStart))); + + // Reset the selection using the existing extent without validation. + newSelection.setWithoutValidation(newSelection.base(), controller->selection().end()); + } + + if (m_lastUpdatedEndPointIsValid) { + relativeEnd = DOMSupport::convertPointToFrame(m_webPage->mainFrame(), focusedFrame, end); + + // Set the selection with validation. + newSelection.setExtent(visiblePositionForPointIgnoringClipping(*focusedFrame, clipPointToFocusNode(relativeEnd))); + + // Reset the selection using the existing base without validation. + newSelection.setWithoutValidation(controller->selection().start(), newSelection.extent()); + } + + if (m_webPage->m_inputHandler->isInputMode()) { + if (updateOrHandleInputSelection(newSelection, relativeStart, relativeEnd)) + return; + } + + if (controller->selection() == newSelection) { + selectionPositionChanged(); + return; + } + + // If the selection size is reduce to less than a character, selection type becomes + // Caret. As long as it is still a range, it's a valid selection. Selection cannot + // be cancelled through this function. + BlackBerry::Platform::IntRectRegion region; + getConsolidatedRegionOfTextQuadsForSelection(newSelection, region); + clipRegionToVisibleContainer(region); + if (!region.isEmpty()) { + // Check if the handles reversed position. + if (m_selectionActive && !newSelection.isBaseFirst()) + m_webPage->m_client->notifySelectionHandlesReversed(); + + controller->setSelection(newSelection); + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::setSelection selection points valid, selection updated"); + } else { + // Requested selection results in an empty selection, skip this change. + selectionPositionChanged(); + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelWarn, "SelectionHandler::setSelection selection points invalid, selection not updated"); + } +} + +// FIXME re-use this in context. Must be updated to include an option to return the href. +// This function should be moved to a new unit file. Names suggetions include DOMQueries +// and NodeTypes. Functions currently in InputHandler.cpp, SelectionHandler.cpp and WebPage.cpp +// can all be moved in. +static Node* enclosingLinkEventParentForNode(Node* node) +{ + if (!node) + return 0; + + Node* linkNode = node->enclosingLinkEventParentOrSelf(); + return linkNode && linkNode->isLink() ? linkNode : 0; +} + +void SelectionHandler::selectAtPoint(const IntPoint& location) +{ + // If point is invalid trigger selection based expansion. + if (location == DOMSupport::InvalidPoint) { + selectObject(WordGranularity); + return; + } + + Node* targetNode; + IntPoint targetPosition; + // FIXME: Factory this get right fat finger code into a helper. + const FatFingersResult lastFatFingersResult = m_webPage->m_touchEventHandler->lastFatFingersResult(); + if (lastFatFingersResult.positionWasAdjusted() && lastFatFingersResult.nodeAsElementIfApplicable()) { + targetNode = lastFatFingersResult.node(FatFingersResult::ShadowContentNotAllowed); + targetPosition = lastFatFingersResult.adjustedPosition(); + } else { + FatFingersResult newFatFingersResult = FatFingers(m_webPage, location, FatFingers::Text).findBestPoint(); + if (!newFatFingersResult.positionWasAdjusted()) + return; + + targetPosition = newFatFingersResult.adjustedPosition(); + targetNode = newFatFingersResult.node(FatFingersResult::ShadowContentNotAllowed); + } + + ASSERT(targetNode); + + // If the node at the point is a link, focus on the entire link, not a word. + if (Node* link = enclosingLinkEventParentForNode(targetNode)) { + selectObject(link); + return; + } + + // selectAtPoint API currently only supports WordGranularity but may be extended in the future. + selectObject(targetPosition, WordGranularity); +} + +static bool expandSelectionToGranularity(Frame* frame, VisibleSelection selection, TextGranularity granularity, bool isInputMode) +{ + ASSERT(frame); + ASSERT(frame->selection()); + + if (!(selection.start().anchorNode() && selection.start().anchorNode()->isTextNode())) + return false; + + if (granularity == WordGranularity) + selection = DOMSupport::visibleSelectionForClosestActualWordStart(selection); + + selection.expandUsingGranularity(granularity); + RefPtr<Range> newRange = selection.toNormalizedRange(); + RefPtr<Range> oldRange = frame->selection()->selection().toNormalizedRange(); + EAffinity affinity = frame->selection()->affinity(); + + if (isInputMode && !frame->editor()->client()->shouldChangeSelectedRange(oldRange.get(), newRange.get(), affinity, false)) + return false; + + return frame->selection()->setSelectedRange(newRange.get(), affinity, true); +} + +void SelectionHandler::selectObject(const IntPoint& location, TextGranularity granularity) +{ + ASSERT(location.x() >= 0 && location.y() >= 0); + ASSERT(m_webPage && m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->selection()); + Frame* focusedFrame = m_webPage->focusedOrMainFrame(); + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::selectObject adjusted points %d, %d", location.x(), location.y()); + + IntPoint relativePoint = DOMSupport::convertPointToFrame(m_webPage->mainFrame(), focusedFrame, location); + VisiblePosition pointLocation(focusedFrame->visiblePositionForPoint(relativePoint)); + VisibleSelection selection = VisibleSelection(pointLocation, pointLocation); + + m_selectionActive = expandSelectionToGranularity(focusedFrame, selection, granularity, m_webPage->m_inputHandler->isInputMode()); +} + +void SelectionHandler::selectObject(TextGranularity granularity) +{ + ASSERT(m_webPage && m_webPage->m_inputHandler); + // Using caret location, must be inside an input field. + if (!m_webPage->m_inputHandler->isInputMode()) + return; + + ASSERT(m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->selection()); + Frame* focusedFrame = m_webPage->focusedOrMainFrame(); + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::selectObject using current selection"); + + // Use the current selection as the selection point. + ASSERT(focusedFrame->selection()->selectionType() != VisibleSelection::NoSelection); + m_selectionActive = expandSelectionToGranularity(focusedFrame, focusedFrame->selection()->selection(), granularity, true /* isInputMode */); +} + +void SelectionHandler::selectObject(Node* node) +{ + if (!node) + return; + + m_selectionActive = true; + + ASSERT(m_webPage && m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->selection()); + Frame* focusedFrame = m_webPage->focusedOrMainFrame(); + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::selectNode"); + + VisibleSelection selection = VisibleSelection::selectionFromContentsOfNode(node); + focusedFrame->selection()->setSelection(selection); +} + +static TextDirection directionOfEnclosingBlock(FrameSelection* selection) +{ + Node* enclosingBlockNode = enclosingBlock(selection->selection().extent().deprecatedNode()); + if (!enclosingBlockNode) + return LTR; + + if (RenderObject* renderer = enclosingBlockNode->renderer()) + return renderer->style()->direction(); + + return LTR; +} + +// Returns > 0 if p1 is "closer" to referencePoint, < 0 if p2 is "closer", 0 if they are equidistant. +// Because text is usually arranged in horizontal rows, distance is measured along the y-axis, with x-axis used only to break ties. +// If rightGravity is true, the right-most x-coordinate is chosen, otherwise teh left-most coordinate is chosen. +static inline int comparePointsToReferencePoint(const IntPoint& p1, const IntPoint& p2, const IntPoint& referencePoint, bool rightGravity) +{ + int dy1 = abs(referencePoint.y() - p1.y()); + int dy2 = abs(referencePoint.y() - p2.y()); + if (dy1 != dy2) + return dy2 - dy1; + + // Same y-coordinate, choose the farthest right (or left) point. + if (p1.x() == p2.x()) + return 0; + + if (p1.x() > p2.x()) + return rightGravity ? 1 : -1; + + return rightGravity ? -1 : 1; +} + +// NOTE/FIXME: Due to r77286, we are getting off-by-one results in the IntRect class counterpart implementation of the +// methods below. As done in r89803, r77928 and a few others, lets use local method to fix it. +// We should keep our eyes very open on it, since it can affect BackingStore very badly. +static IntPoint minXMinYCorner(const IntRect& rect) { return rect.location(); } // typically topLeft +static IntPoint maxXMinYCorner(const IntRect& rect) { return IntPoint(rect.x() + rect.width() - 1, rect.y()); } // typically topRight +static IntPoint minXMaxYCorner(const IntRect& rect) { return IntPoint(rect.x(), rect.y() + rect.height() - 1); } // typically bottomLeft +static IntPoint maxXMaxYCorner(const IntRect& rect) { return IntPoint(rect.x() + rect.width() - 1, rect.y() + rect.height() - 1); } // typically bottomRight + +// The caret is a one-pixel wide line down either the right or left edge of a +// rect, depending on the text direction. +static inline bool caretIsOnLeft(bool isStartCaret, bool isRTL) +{ + if (isStartCaret) + return !isRTL; + + return isRTL; +} + +static inline IntPoint caretLocationForRect(const IntRect& rect, bool isStartCaret, bool isRTL) +{ + return caretIsOnLeft(isStartCaret, isRTL) ? minXMinYCorner(rect) : maxXMinYCorner(rect); +} + +static inline IntPoint caretComparisonPointForRect(const IntRect& rect, bool isStartCaret, bool isRTL) +{ + if (isStartCaret) + return caretIsOnLeft(isStartCaret, isRTL) ? minXMinYCorner(rect) : maxXMinYCorner(rect); + + return caretIsOnLeft(isStartCaret, isRTL) ? minXMaxYCorner(rect) : maxXMaxYCorner(rect); +} + +static void adjustCaretRects(IntRect& startCaret, bool isStartCaretClippedOut, + IntRect& endCaret, bool isEndCaretClippedOut, + const std::vector<BlackBerry::Platform::IntRect> rectList, + const IntPoint& startReferencePoint, + const IntPoint& endReferencePoint, + bool isRTL) +{ + // startReferencePoint is the best guess at the top left of the selection; endReferencePoint is the best guess at the bottom right. + if (isStartCaretClippedOut) + startCaret.setLocation(DOMSupport::InvalidPoint); + else { + startCaret = rectList[0]; + startCaret.setLocation(caretLocationForRect(startCaret, true, isRTL)); + } + + if (isEndCaretClippedOut) + endCaret.setLocation(DOMSupport::InvalidPoint); + else { + endCaret = rectList[0]; + endCaret.setLocation(caretLocationForRect(endCaret, false, isRTL)); + } + + if (isStartCaretClippedOut && isEndCaretClippedOut) + return; + + // Reset width to 1 as we are strictly interested in caret location. + startCaret.setWidth(1); + endCaret.setWidth(1); + + for (unsigned i = 1; i < rectList.size(); i++) { + IntRect currentRect(rectList[i]); + + // Compare and update the start and end carets with their respective reference points. + if (!isStartCaretClippedOut && comparePointsToReferencePoint( + caretComparisonPointForRect(currentRect, true, isRTL), + caretComparisonPointForRect(startCaret, true, isRTL), + startReferencePoint, isRTL) > 0) { + startCaret.setLocation(caretLocationForRect(currentRect, true, isRTL)); + startCaret.setHeight(currentRect.height()); + } + + if (!isEndCaretClippedOut && comparePointsToReferencePoint( + caretComparisonPointForRect(currentRect, false, isRTL), + caretComparisonPointForRect(endCaret, false, isRTL), + endReferencePoint, !isRTL) > 0) { + endCaret.setLocation(caretLocationForRect(currentRect, false, isRTL)); + endCaret.setHeight(currentRect.height()); + } + } +} + +void SelectionHandler::clipRegionToVisibleContainer(BlackBerry::Platform::IntRectRegion& region) +{ + ASSERT(m_webPage->m_mainFrame && m_webPage->m_mainFrame->view()); + + Frame* frame = m_webPage->focusedOrMainFrame(); + + // Don't allow the region to extend outside of the all its ancestor frames' visible area. + if (frame != m_webPage->mainFrame()) { + IntRect containingContentRect; + containingContentRect = m_webPage->getRecursiveVisibleWindowRect(frame->view(), true /* no clip to main frame window */); + containingContentRect = m_webPage->m_mainFrame->view()->windowToContents(containingContentRect); + region = intersectRegions(BlackBerry::Platform::IntRectRegion(containingContentRect), region); + } + + // Don't allow the region to extend outside of the input field. + if (m_webPage->m_inputHandler->isInputMode() + && frame->document()->focusedNode() + && frame->document()->focusedNode()->renderer()) { + + // Adjust the bounding box to the frame offset. + IntRect boundingBox(frame->document()->focusedNode()->renderer()->absoluteBoundingBoxRect()); + boundingBox = m_webPage->mainFrame()->view()->windowToContents(frame->view()->contentsToWindow(boundingBox)); + + region = intersectRegions(BlackBerry::Platform::IntRectRegion(boundingBox), region); + } +} + +static IntPoint referencePoint(const VisiblePosition& position, const IntRect& boundingRect, const IntPoint& framePosition, bool isStartCaret, bool isRTL) +{ + // If one of the carets is invalid (this happens, for instance, if the + // selection ends in an empty div) fall back to using the corner of the + // entire region (which is already in frame coordinates so doesn't need + // adjusting). + IntRect startCaretBounds(position.absoluteCaretBounds()); + if (startCaretBounds.isEmpty()) + startCaretBounds = boundingRect; + else + startCaretBounds.move(framePosition.x(), framePosition.y()); + + return caretComparisonPointForRect(startCaretBounds, isStartCaret, isRTL); +} + +// Note: This is the only function in SelectionHandler in which the coordinate +// system is not entirely WebKit. +void SelectionHandler::selectionPositionChanged(bool visualChangeOnly) +{ + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::selectionPositionChanged visibleChangeOnly = %s", visualChangeOnly ? "true" : "false"); + + // This method can get called during WebPage shutdown process. + // If that is the case, just bail out since the client is not + // in a safe state of trust to request anything else from it. + if (!m_webPage->m_mainFrame) + return; + + if (m_webPage->m_inputHandler->isInputMode() && m_webPage->m_inputHandler->processingChange()) { + m_webPage->m_client->cancelSelectionVisuals(); + return; + } + + if (m_caretActive || (m_webPage->m_inputHandler->isInputMode() && m_webPage->focusedOrMainFrame()->selection()->isCaret())) { + // This may update the caret to no longer be active. + caretPositionChanged(); + } + + // Enter selection mode if selection type is RangeSelection, and disable selection if + // selection is active and becomes caret selection. + Frame* frame = m_webPage->focusedOrMainFrame(); + IntPoint framePos = m_webPage->frameOffset(frame); + if (m_selectionActive && (m_caretActive || frame->selection()->isNone())) + m_selectionActive = false; + else if (frame->selection()->isRange()) + m_selectionActive = true; + else if (!m_selectionActive) + return; + + IntRect startCaret; + IntRect endCaret; + + // Get the text rects from the selections range. + BlackBerry::Platform::IntRectRegion region; + getConsolidatedRegionOfTextQuadsForSelection(frame->selection()->selection(), region); + + // If there is no change in selected text and the visual rects + // have not changed then don't bother notifying anything. + if (visualChangeOnly && m_lastSelectionRegion.isEqual(region)) + return; + + m_lastSelectionRegion = region; + + if (!region.isEmpty()) { + IntRect unclippedStartCaret; + IntRect unclippedEndCaret; + + bool isRTL = directionOfEnclosingBlock(frame->selection()) == RTL; + + std::vector<BlackBerry::Platform::IntRect> rectList = region.rects(); + + IntPoint startCaretReferencePoint = referencePoint(frame->selection()->selection().visibleStart(), region.extents(), framePos, true /* isStartCaret */, isRTL); + IntPoint endCaretReferencePoint = referencePoint(frame->selection()->selection().visibleEnd(), region.extents(), framePos, false /* isStartCaret */, isRTL); + + adjustCaretRects(unclippedStartCaret, false /* unclipped */, unclippedEndCaret, false /* unclipped */, rectList, startCaretReferencePoint, endCaretReferencePoint, isRTL); + + clipRegionToVisibleContainer(region); + +#if SHOWDEBUG_SELECTIONHANDLER // Don't rely just on DEBUG_SELECTION to avoid loop. + for (unsigned int i = 0; i < rectList.size(); i++) + DEBUG_SELECTION(BlackBerry::Platform::LogLevelCritical, "Rect list - Unmodified #%d, (%d, %d) (%d x %d)", i, rectList[i].x(), rectList[i].y(), rectList[i].width(), rectList[i].height()); + for (unsigned int i = 0; i < region.numRects(); i++) + DEBUG_SELECTION(BlackBerry::Platform::LogLevelCritical, "Rect list - Consolidated #%d, (%d, %d) (%d x %d)", i, region.rects()[i].x(), region.rects()[i].y(), region.rects()[i].width(), region.rects()[i].height()); +#endif + + bool shouldCareAboutPossibleClippedOutSelection = frame != m_webPage->mainFrame() || m_webPage->m_inputHandler->isInputMode(); + + if (!region.isEmpty() || shouldCareAboutPossibleClippedOutSelection) { + // Adjust the handle markers to be at the end of the painted rect. When selecting links + // and other elements that may have a larger visible area than needs to be rendered a gap + // can exist between the handle and overlay region. + + bool shouldClipStartCaret = !region.isRectInRegion(unclippedStartCaret); + bool shouldClipEndCaret = !region.isRectInRegion(unclippedEndCaret); + + // Find the top corner and bottom corner. + std::vector<BlackBerry::Platform::IntRect> clippedRectList = region.rects(); + adjustCaretRects(startCaret, shouldClipStartCaret, endCaret, shouldClipEndCaret, clippedRectList, startCaretReferencePoint, endCaretReferencePoint, isRTL); + + // Translate the caret values as they must be in transformed coordinates. + if (!shouldClipStartCaret) { + startCaret = m_webPage->mapToTransformed(startCaret); + m_webPage->clipToTransformedContentsRect(startCaret); + } + + if (!shouldClipEndCaret) { + endCaret = m_webPage->mapToTransformed(endCaret); + m_webPage->clipToTransformedContentsRect(endCaret); + } + } + } + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::selectionPositionChanged Start Rect=(%d, %d) (%d x %d) End Rect=(%d, %d) (%d x %d)", + startCaret.x(), startCaret.y(), startCaret.width(), startCaret.height(), endCaret.x(), endCaret.y(), endCaret.width(), endCaret.height()); + + + m_webPage->m_client->notifySelectionDetailsChanged(startCaret, endCaret, region); +} + +// NOTE: This function is not in WebKit coordinates. +void SelectionHandler::caretPositionChanged() +{ + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::caretPositionChanged"); + + IntRect caretLocation; + // If the input field is not active, we must be turning off the caret. + if (!m_webPage->m_inputHandler->isInputMode() && m_caretActive) { + m_caretActive = false; + // Send an empty caret change to turn off the caret. + m_webPage->m_client->notifyCaretChanged(caretLocation, m_webPage->m_touchEventHandler->lastFatFingersResult().isTextInput() /* userTouchTriggered */); + return; + } + + ASSERT(m_webPage && m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->selection()); + + // This function should only reach this point if input mode is active. + ASSERT(m_webPage->m_inputHandler->isInputMode()); + + if (m_webPage->focusedOrMainFrame()->selection()->selectionType() == VisibleSelection::CaretSelection) { + IntPoint frameOffset = m_webPage->frameOffset(m_webPage->focusedOrMainFrame()); + + caretLocation = m_webPage->focusedOrMainFrame()->selection()->selection().visibleStart().absoluteCaretBounds(); + caretLocation.move(frameOffset.x(), frameOffset.y()); + + // Clip against the containing frame and node boundaries. + BlackBerry::Platform::IntRectRegion region(caretLocation); + clipRegionToVisibleContainer(region); + caretLocation = region.extents(); + } + + m_caretActive = !caretLocation.isEmpty(); + + DEBUG_SELECTION(BlackBerry::Platform::LogLevelInfo, "SelectionHandler::caretPositionChanged caret Rect %d, %d, %dx%d", + caretLocation.x(), caretLocation.y(), caretLocation.width(), caretLocation.height()); + + caretLocation = m_webPage->mapToTransformed(caretLocation); + m_webPage->clipToTransformedContentsRect(caretLocation); + + m_webPage->m_client->notifyCaretChanged(caretLocation, m_webPage->m_touchEventHandler->lastFatFingersResult().isTextInput() /* userTouchTriggered */); +} + +bool SelectionHandler::selectionContains(const IntPoint& point) +{ + ASSERT(m_webPage && m_webPage->focusedOrMainFrame() && m_webPage->focusedOrMainFrame()->selection()); + return m_webPage->focusedOrMainFrame()->selection()->contains(point); +} + +} +} diff --git a/Source/WebKit/blackberry/WebKitSupport/SelectionHandler.h b/Source/WebKit/blackberry/WebKitSupport/SelectionHandler.h new file mode 100644 index 000000000..8c5fe7637 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/SelectionHandler.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SelectionHandler_h +#define SelectionHandler_h + +#include "BlackBerryPlatformIntRectRegion.h" +#include "BlackBerryPlatformPrimitives.h" +#include "TextGranularity.h" + +namespace WTF { +class String; +} + +namespace WebCore { +class IntPoint; +class IntRect; +class Node; +class VisiblePosition; +class VisibleSelection; +} + +namespace BlackBerry { + +namespace WebKit { + +class WebPagePrivate; +class WebString; + +class SelectionHandler { +public: + SelectionHandler(WebPagePrivate*); + ~SelectionHandler(); + + bool isSelectionActive() { return m_selectionActive; } + void setSelectionActive(bool active) { m_selectionActive = active; } + + void cancelSelection(); + WebString selectedText() const; + + bool selectionContains(const WebCore::IntPoint&); + + void setSelection(const WebCore::IntPoint& start, const WebCore::IntPoint& end); + void selectAtPoint(const WebCore::IntPoint&); + void selectObject(const WebCore::IntPoint&, WebCore::TextGranularity); + void selectObject(WebCore::TextGranularity); + void selectObject(WebCore::Node*); + + void selectionPositionChanged(bool visualChangeOnly = false); + + void setCaretPosition(const WebCore::IntPoint&); + + bool lastUpdatedEndPointIsValid() const { return m_lastUpdatedEndPointIsValid; } + +private: + void caretPositionChanged(); + void getConsolidatedRegionOfTextQuadsForSelection(const WebCore::VisibleSelection&, BlackBerry::Platform::IntRectRegion&) const; + void clipRegionToVisibleContainer(BlackBerry::Platform::IntRectRegion&); + bool updateOrHandleInputSelection(WebCore::VisibleSelection& newSelection, const WebCore::IntPoint& relativeStart + , const WebCore::IntPoint& relativeEnd); + WebCore::Node* DOMContainerNodeForVisiblePosition(const WebCore::VisiblePosition&) const; + bool shouldUpdateSelectionOrCaretForPoint(const WebCore::IntPoint&, const WebCore::IntRect&, bool startCaret = true) const; + unsigned short extendSelectionToFieldBoundary(bool isStartHandle, const WebCore::IntPoint& selectionPoint, WebCore::VisibleSelection& newSelection); + WebCore::IntPoint clipPointToFocusNode(const WebCore::IntPoint&); + + WebPagePrivate* m_webPage; + + bool m_selectionActive; + bool m_caretActive; + bool m_lastUpdatedEndPointIsValid; + BlackBerry::Platform::IntRectRegion m_lastSelectionRegion; +}; + +} +} + +#endif // SelectionHandler_h diff --git a/Source/WebKit/blackberry/WebKitSupport/SurfacePool.cpp b/Source/WebKit/blackberry/WebKitSupport/SurfacePool.cpp new file mode 100644 index 000000000..2642f39e3 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/SurfacePool.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "SurfacePool.h" + +#include "PlatformContextSkia.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "BackingStoreCompositingSurface.h" +#endif + +#include <BlackBerryPlatformLog.h> +#include <BlackBerryPlatformMisc.h> +#include <BlackBerryPlatformScreen.h> +#include <BlackBerryPlatformSettings.h> + +#define SHARED_PIXMAP_GROUP "webkit_backingstore_group" + +namespace BlackBerry { +namespace WebKit { + +#if USE(ACCELERATED_COMPOSITING) && ENABLE_COMPOSITING_SURFACE +static PassRefPtr<BackingStoreCompositingSurface> createCompositingSurface() +{ + BlackBerry::Platform::IntSize screenSize = BlackBerry::Platform::Graphics::Screen::size(); + return BackingStoreCompositingSurface::create(screenSize, false /*doubleBuffered*/); +} +#endif + +SurfacePool* SurfacePool::globalSurfacePool() +{ + static SurfacePool* s_instance = 0; + if (!s_instance) + s_instance = new SurfacePool; + return s_instance; +} + +SurfacePool::SurfacePool() + : m_visibleTileBuffer(0) +#if USE(ACCELERATED_COMPOSITING) + , m_compositingSurface(0) +#endif + , m_tileRenderingSurface(0) + , m_backBuffer(0) + , m_initialized(false) + , m_buffersSuspended(false) +{ +} + +void SurfacePool::initialize(const BlackBerry::Platform::IntSize& tileSize) +{ + if (m_initialized) + return; + m_initialized = true; + + const unsigned numberOfTiles = BlackBerry::Platform::Settings::get()->numberOfBackingStoreTiles(); + const unsigned maxNumberOfTiles = BlackBerry::Platform::Settings::get()->maximumNumberOfBackingStoreTilesAcrossProcesses(); + + if (numberOfTiles) { // Only allocate if we actually use a backingstore. + unsigned byteLimit = (maxNumberOfTiles /*pool*/ + 2 /*visible tile buffer, backbuffer*/) * tileSize.width() * tileSize.height() * 4; + bool success = BlackBerry::Platform::Graphics::createPixmapGroup(SHARED_PIXMAP_GROUP, byteLimit); + if (!success) { + BlackBerry::Platform::log(BlackBerry::Platform::LogLevelWarn, + "Shared buffer pool could not be set up, using regular memory allocation instead."); + } + } + + m_tileRenderingSurface = BlackBerry::Platform::Graphics::drawingSurface(); + +#if USE(ACCELERATED_COMPOSITING) && ENABLE_COMPOSITING_SURFACE + m_compositingSurface = createCompositingSurface(); +#endif + + if (!numberOfTiles) + return; // we only use direct rendering when 0 tiles are specified. + + // Create the shared backbuffer. + m_backBuffer = reinterpret_cast<unsigned>(new TileBuffer(tileSize)); + + for (size_t i = 0; i < numberOfTiles; ++i) + m_tilePool.append(BackingStoreTile::create(tileSize, BackingStoreTile::DoubleBuffered)); +} + +PlatformGraphicsContext* SurfacePool::createPlatformGraphicsContext(BlackBerry::Platform::Graphics::Drawable* drawable) const +{ + return new WebCore::PlatformContextSkia(drawable); +} + +PlatformGraphicsContext* SurfacePool::lockTileRenderingSurface() const +{ + if (!m_tileRenderingSurface) + return 0; + + return createPlatformGraphicsContext(BlackBerry::Platform::Graphics::lockBufferDrawable(m_tileRenderingSurface)); +} + +void SurfacePool::releaseTileRenderingSurface(PlatformGraphicsContext* context) const +{ + if (!m_tileRenderingSurface) + return; + + delete context; + BlackBerry::Platform::Graphics::releaseBufferDrawable(m_tileRenderingSurface); +} + +void SurfacePool::initializeVisibleTileBuffer(const BlackBerry::Platform::IntSize& visibleSize) +{ + if (!m_visibleTileBuffer || m_visibleTileBuffer->size() != visibleSize) { + delete m_visibleTileBuffer; + m_visibleTileBuffer = BackingStoreTile::create(visibleSize, BackingStoreTile::SingleBuffered); + } +} + +TileBuffer* SurfacePool::backBuffer() const +{ + ASSERT(m_backBuffer); + return reinterpret_cast<TileBuffer*>(m_backBuffer); +} + +#if USE(ACCELERATED_COMPOSITING) +BackingStoreCompositingSurface* SurfacePool::compositingSurface() const +{ + return m_compositingSurface.get(); +} +#endif + +void SurfacePool::notifyScreenRotated() +{ +#if USE(ACCELERATED_COMPOSITING) && ENABLE_COMPOSITING_SURFACE + // Recreate compositing surface at new screen resolution. + m_compositingSurface = createCompositingSurface(); +#endif +} + +std::string SurfacePool::sharedPixmapGroup() const +{ + return SHARED_PIXMAP_GROUP; +} + +void SurfacePool::createBuffers() +{ + if (!m_initialized || m_tilePool.isEmpty()) + return; + + // Create the tile pool. + for (size_t i = 0; i < m_tilePool.size(); ++i) + BlackBerry::Platform::Graphics::createPixmapBuffer(m_tilePool[i]->frontBuffer()->nativeBuffer()); + + if (m_visibleTileBuffer) + BlackBerry::Platform::Graphics::createPixmapBuffer(m_visibleTileBuffer->frontBuffer()->nativeBuffer()); + + if (backBuffer()) + BlackBerry::Platform::Graphics::createPixmapBuffer(backBuffer()->nativeBuffer()); + + m_buffersSuspended = false; +} + +void SurfacePool::releaseBuffers() +{ + if (!m_initialized || m_tilePool.isEmpty()) + return; + + m_buffersSuspended = true; + + // Release the tile pool. + for (size_t i = 0; i < m_tilePool.size(); ++i) { + m_tilePool[i]->frontBuffer()->clearRenderedRegion(); + BlackBerry::Platform::Graphics::destroyPixmapBuffer(m_tilePool[i]->frontBuffer()->nativeBuffer()); + } + + if (m_visibleTileBuffer) { + m_visibleTileBuffer->frontBuffer()->clearRenderedRegion(); + BlackBerry::Platform::Graphics::destroyPixmapBuffer(m_visibleTileBuffer->frontBuffer()->nativeBuffer()); + } + + if (backBuffer()) { + backBuffer()->clearRenderedRegion(); + BlackBerry::Platform::Graphics::destroyPixmapBuffer(backBuffer()->nativeBuffer()); + } +} + +} +} diff --git a/Source/WebKit/blackberry/WebKitSupport/SurfacePool.h b/Source/WebKit/blackberry/WebKitSupport/SurfacePool.h new file mode 100644 index 000000000..fa88a5d6a --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/SurfacePool.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SurfacePool_h +#define SurfacePool_h + +#include "BackingStoreTile.h" + +#include "PlatformContextSkia.h" + +#include <BlackBerryPlatformGraphics.h> +#include <BlackBerryPlatformPrimitives.h> +#include <wtf/Vector.h> + +#define ENABLE_COMPOSITING_SURFACE 1 + +namespace BlackBerry { +namespace WebKit { + +class BackingStoreCompositingSurface; + +class SurfacePool { +public: + static SurfacePool* globalSurfacePool(); + + void initialize(const BlackBerry::Platform::IntSize&); + + int isActive() const { return !m_tilePool.isEmpty() && !m_buffersSuspended; } + int isEmpty() const { return m_tilePool.isEmpty(); } + int size() const { return m_tilePool.size(); } + + typedef WTF::Vector<BackingStoreTile*> TileList; + const TileList tileList() const { return m_tilePool; } + + PlatformGraphicsContext* createPlatformGraphicsContext(BlackBerry::Platform::Graphics::Drawable*) const; + PlatformGraphicsContext* lockTileRenderingSurface() const; + void releaseTileRenderingSurface(PlatformGraphicsContext*) const; + BackingStoreTile* visibleTileBuffer() const { return m_visibleTileBuffer; } + + void initializeVisibleTileBuffer(const BlackBerry::Platform::IntSize&); + + // This is a shared back buffer that is used by all the tiles since + // only one tile will be rendering it at a time and we invalidate + // the whole tile every time we render by copying from the front + // buffer those portions that we don't render. This allows us to + // have N+1 tilebuffers rather than N*2 for our double buffered + // backingstore. + TileBuffer* backBuffer() const; + + BackingStoreCompositingSurface* compositingSurface() const; + + void notifyScreenRotated(); + + std::string sharedPixmapGroup() const; + + void releaseBuffers(); + void createBuffers(); + +private: + // This is necessary so BackingStoreTile can atomically swap buffers with m_backBuffer. + friend class BackingStoreTile; + + SurfacePool(); + + TileList m_tilePool; + BackingStoreTile* m_visibleTileBuffer; +#if USE(ACCELERATED_COMPOSITING) + RefPtr<BackingStoreCompositingSurface> m_compositingSurface; +#endif + BlackBerry::Platform::Graphics::Buffer* m_tileRenderingSurface; + unsigned m_backBuffer; + bool m_initialized; // SurfacePool has been set up, with or without buffers. + bool m_buffersSuspended; // Buffer objects exist, but pixel memory has been freed. +}; +} +} + +#endif // SurfacePool_h diff --git a/Source/WebKit/blackberry/WebKitSupport/TileIndex.h b/Source/WebKit/blackberry/WebKitSupport/TileIndex.h new file mode 100644 index 000000000..3149847c9 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/TileIndex.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009, 2010, 2011 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef TileIndex_h +#define TileIndex_h + +#include <limits> + +namespace BlackBerry { +namespace WebKit { + +class TileIndex { +public: + TileIndex() + : m_i(std::numeric_limits<unsigned int>::max()) + , m_j(std::numeric_limits<unsigned int>::max()) { } + TileIndex(unsigned int i, unsigned int j) + : m_i(i) + , m_j(j) { } + ~TileIndex() { } + + unsigned int i() const { return m_i; } + unsigned int j() const { return m_j; } + void setIndex(unsigned int i, unsigned int j) + { + m_i = i; + m_j = j; + } + +private: + bool m_isValid; + unsigned int m_i; + unsigned int m_j; +}; + +inline bool operator==(const BlackBerry::WebKit::TileIndex& a, const BlackBerry::WebKit::TileIndex& b) +{ + return a.i() == b.i() && a.j() == b.j(); +} + +inline bool operator!=(const BlackBerry::WebKit::TileIndex& a, const BlackBerry::WebKit::TileIndex& b) +{ + return a.i() != b.i() || a.j() != b.j(); +} +} +} + +#endif // TileIndex_h diff --git a/Source/WebKit/blackberry/WebKitSupport/TileIndexHash.h b/Source/WebKit/blackberry/WebKitSupport/TileIndexHash.h new file mode 100644 index 000000000..0d4633b75 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/TileIndexHash.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009, 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef TileIndexHash_h +#define TileIndexHash_h + +#include "TileIndex.h" +#include <limits> +#include <wtf/HashMap.h> + +using BlackBerry::WebKit::TileIndex; + +namespace WTF { + +template<> struct IntHash<TileIndex> { + static unsigned hash(const TileIndex& key) { return intHash((static_cast<uint64_t>(key.i()) << 32 | key.j())); } + static bool equal(const TileIndex& a, const TileIndex& b) { return a == b; } + static const bool safeToCompareToEmptyOrDeleted = true; +}; +template<> struct DefaultHash<TileIndex> { + typedef IntHash<TileIndex> Hash; +}; + +template<> struct HashTraits<TileIndex> : GenericHashTraits<TileIndex> { + static const bool emptyValueIsZero = false; + static const bool needsDestruction = false; + static TileIndex emptyValue() { return TileIndex(); } + static void constructDeletedValue(TileIndex& slot) + { + new (&slot) TileIndex(std::numeric_limits<unsigned int>::max() - 1, + std::numeric_limits<unsigned int>::max() - 1); + } + static bool isDeletedValue(const TileIndex& value) + { + return value.i() == (std::numeric_limits<unsigned int>::max() - 1) + && value.j() == (std::numeric_limits<unsigned int>::max() - 1); + } +}; +} // namespace WTF + +#endif // TileIndexHash_h diff --git a/Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.cpp b/Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.cpp new file mode 100644 index 000000000..cfe559af0 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.cpp @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "TouchEventHandler.h" + +#include "DOMSupport.h" +#include "Document.h" +#include "DocumentMarkerController.h" +#include "FocusController.h" +#include "Frame.h" +#include "FrameView.h" +#include "HTMLAnchorElement.h" +#include "HTMLAreaElement.h" +#include "HTMLImageElement.h" +#include "HTMLInputElement.h" +#include "HTMLNames.h" +#include "HTMLPlugInElement.h" +#include "InputHandler.h" +#include "IntRect.h" +#include "IntSize.h" +#include "Node.h" +#include "Page.h" +#include "PlatformMouseEvent.h" +#include "PlatformTouchEvent.h" +#include "RenderLayer.h" +#include "RenderTheme.h" +#include "RenderView.h" +#include "RenderedDocumentMarker.h" +#include "SelectionHandler.h" +#include "WebPage_p.h" + +#include <wtf/MathExtras.h> + +using namespace WebCore; +using namespace WTF; + +namespace BlackBerry { +namespace WebKit { + +static bool hasMouseMoveListener(Element* element) +{ + ASSERT(element); + return element->hasEventListeners(eventNames().mousemoveEvent) || element->document()->hasEventListeners(eventNames().mousemoveEvent); +} + +static bool hasTouchListener(Element* element) +{ + ASSERT(element); + return element->hasEventListeners(eventNames().touchstartEvent) + || element->hasEventListeners(eventNames().touchmoveEvent) + || element->hasEventListeners(eventNames().touchcancelEvent) + || element->hasEventListeners(eventNames().touchendEvent); +} + +static bool elementExpectsMouseEvents(Element* element) +{ + // Make sure we are not operating a shadow node here, since the webpages + // aren't able to attach event listeners to shadow content. + ASSERT(element); + while (element->isInShadowTree()) + element = toElement(element->shadowAncestorNode()); + + return hasMouseMoveListener(element) && !hasTouchListener(element); +} + +static bool shouldConvertTouchToMouse(Element* element) +{ + if (!element) + return false; + + // Range element are a special case that require natural mouse events in order to allow + // dragging of the slider handle. + if (element->hasTagName(HTMLNames::inputTag)) { + HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(element); + if (inputElement->isRangeControl()) + return true; + } + + if ((element->hasTagName(HTMLNames::objectTag) || element->hasTagName(HTMLNames::embedTag)) && static_cast<HTMLPlugInElement*>(element)) + return true; + + // Check if the element has a mouse listener and no touch listener. If so, + // the field will require touch events be converted to mouse events to function properly. + if (elementExpectsMouseEvents(element)) + return true; + + return false; +} + +TouchEventHandler::TouchEventHandler(WebPagePrivate* webpage) + : m_webPage(webpage) + , m_didCancelTouch(false) + , m_convertTouchToMouse(false) + , m_existingTouchMode(ProcessedTouchEvents) +{ +} + +TouchEventHandler::~TouchEventHandler() +{ +} + +bool TouchEventHandler::shouldSuppressMouseDownOnTouchDown() const +{ + return m_lastFatFingersResult.isTextInput() || m_webPage->m_inputHandler->isInputMode() || m_webPage->m_selectionHandler->isSelectionActive(); +} + +void TouchEventHandler::touchEventCancel() +{ + m_webPage->m_inputHandler->processPendingKeyboardVisibilityChange(); + + if (!shouldSuppressMouseDownOnTouchDown()) { + // Input elements delay mouse down and do not need to be released on touch cancel. + m_webPage->m_page->focusController()->focusedOrMainFrame()->eventHandler()->setMousePressed(false); + } + m_convertTouchToMouse = false; + m_didCancelTouch = true; + + // If we cancel a single touch event, we need to also clean up any hover + // state we get into by synthetically moving the mouse to the m_fingerPoint. + Element* elementUnderFatFinger = m_lastFatFingersResult.nodeAsElementIfApplicable(); + if (elementUnderFatFinger && elementUnderFatFinger->renderer()) { + + HitTestRequest request(HitTestRequest::FingerUp); + // The HitTestResult point is not actually needed. + HitTestResult result(IntPoint::zero()); + result.setInnerNode(elementUnderFatFinger); + + Document* document = elementUnderFatFinger->document(); + ASSERT(document); + document->renderView()->layer()->updateHoverActiveState(request, result); + document->updateStyleIfNeeded(); + // Updating the document style may destroy the renderer. + if (elementUnderFatFinger->renderer()) + elementUnderFatFinger->renderer()->repaint(); + ASSERT(!elementUnderFatFinger->hovered()); + } + + m_lastFatFingersResult.reset(); +} + +void TouchEventHandler::touchEventCancelAndClearFocusedNode() +{ + touchEventCancel(); + m_webPage->clearFocusNode(); +} + +void TouchEventHandler::touchHoldEvent() +{ + // This is a hack for our hack that converts the touch pressed event that we've delayed because the user has focused a input field + // to the page as a mouse pressed event. + if (shouldSuppressMouseDownOnTouchDown()) + handleFatFingerPressed(); + + // Clear the focus ring indication if tap-and-hold'ing on a link. + if (m_lastFatFingersResult.node() && m_lastFatFingersResult.node()->isLink()) + m_webPage->clearFocusNode(); +} + +bool TouchEventHandler::handleTouchPoint(Platform::TouchPoint& point) +{ + switch (point.m_state) { + case Platform::TouchPoint::TouchPressed: + { + m_lastFatFingersResult.reset(); // Theoretically this shouldn't be required. Keep it just in case states get mangled. + m_didCancelTouch = false; + m_lastScreenPoint = point.m_screenPos; + + IntPoint contentPos(m_webPage->mapFromViewportToContents(point.m_pos)); + + m_lastFatFingersResult = FatFingers(m_webPage, contentPos, FatFingers::ClickableElement).findBestPoint(); + + Element* elementUnderFatFinger = 0; + if (m_lastFatFingersResult.positionWasAdjusted() && m_lastFatFingersResult.node()) { + ASSERT(m_lastFatFingersResult.node()->isElementNode()); + elementUnderFatFinger = m_lastFatFingersResult.nodeAsElementIfApplicable(); + } + + // Set or reset the touch mode. + Element* possibleTargetNodeForMouseMoveEvents = static_cast<Element*>(m_lastFatFingersResult.positionWasAdjusted() ? elementUnderFatFinger : m_lastFatFingersResult.node()); + m_convertTouchToMouse = shouldConvertTouchToMouse(possibleTargetNodeForMouseMoveEvents); + + if (elementUnderFatFinger) + drawTapHighlight(); + + // Lets be conservative here: since we have problems on major website having + // mousemove listener for no good reason (e.g. google.com, desktop edition), + // let only delay client notifications when there is not input text node involved. + if (m_convertTouchToMouse + && (m_webPage->m_inputHandler->isInputMode() && !m_lastFatFingersResult.isTextInput())) { + m_webPage->m_inputHandler->setDelayKeyboardVisibilityChange(true); + handleFatFingerPressed(); + } else if (!shouldSuppressMouseDownOnTouchDown()) + handleFatFingerPressed(); + + return true; + } + case Platform::TouchPoint::TouchReleased: + { + // Apply any suppressed changes. This does not eliminate the need + // for the show after the handling of fat finger pressed as it may + // have triggered a state change. + m_webPage->m_inputHandler->processPendingKeyboardVisibilityChange(); + + if (shouldSuppressMouseDownOnTouchDown()) + handleFatFingerPressed(); + + // The rebase has eliminated a necessary event when the mouse does not + // trigger an actual selection change preventing re-showing of the + // keyboard. If input mode is active, call showVirtualKeyboard which + // will update the state and display keyboard if needed. + if (m_webPage->m_inputHandler->isInputMode()) + m_webPage->m_inputHandler->notifyClientOfKeyboardVisibilityChange(true); + + IntPoint adjustedPoint; + if (m_convertTouchToMouse) { + adjustedPoint = point.m_pos; + m_convertTouchToMouse = false; + } else // Fat finger point in viewport coordinates. + adjustedPoint = m_webPage->mapFromContentsToViewport(m_lastFatFingersResult.adjustedPosition()); + + PlatformMouseEvent mouseEvent(adjustedPoint, m_lastScreenPoint, MouseEventReleased, 1, LeftButton, TouchScreen); + m_webPage->handleMouseEvent(mouseEvent); + m_lastFatFingersResult.reset(); // Reset the fat finger result as its no longer valid when a user's finger is not on the screen. + + unsigned spellLength = spellCheck(point); + if (spellLength) { + unsigned end = m_webPage->m_inputHandler->caretPosition(); + unsigned start = end - spellLength; + m_webPage->m_client->requestSpellingSuggestionsForString(start, end); + } + return true; + } + case Platform::TouchPoint::TouchMoved: + if (m_convertTouchToMouse) { + PlatformMouseEvent mouseEvent(point.m_pos, m_lastScreenPoint, MouseEventMoved, 1, LeftButton, TouchScreen); + m_lastScreenPoint = point.m_screenPos; + if (!m_webPage->handleMouseEvent(mouseEvent)) { + m_convertTouchToMouse = false; + return false; + } + return true; + } + break; + default: + break; + } + return false; +} + +unsigned TouchEventHandler::spellCheck(Platform::TouchPoint& touchPoint) +{ + Element* elementUnderFatFinger = m_lastFatFingersResult.nodeAsElementIfApplicable(); + if (!m_lastFatFingersResult.isTextInput() || !elementUnderFatFinger) + return 0; + + IntPoint contentPos(m_webPage->mapFromViewportToContents(touchPoint.m_pos)); + contentPos = DOMSupport::convertPointToFrame(m_webPage->mainFrame(), m_webPage->focusedOrMainFrame(), contentPos); + + Document* document = elementUnderFatFinger->document(); + ASSERT(document); + RenderedDocumentMarker* marker = document->markers()->renderedMarkerContainingPoint(contentPos, DocumentMarker::Spelling); + if (!marker) + return 0; + + IntRect rect = marker->renderedRect(); + IntPoint newContentPos = IntPoint(rect.x() + rect.width(), rect.y() + rect.height() / 2); + Frame* frame = m_webPage->focusedOrMainFrame(); + if (frame != m_webPage->mainFrame()) + newContentPos = m_webPage->mainFrame()->view()->windowToContents(frame->view()->contentsToWindow(newContentPos)); + m_lastFatFingersResult.m_adjustedPosition = newContentPos; + m_lastFatFingersResult.m_positionWasAdjusted = true; + return marker->endOffset() - marker->startOffset(); +} + +void TouchEventHandler::handleFatFingerPressed() +{ + if (!m_didCancelTouch) { + + // First update the mouse position with a MouseMoved event. + PlatformMouseEvent mouseMoveEvent(m_webPage->mapFromContentsToViewport(m_lastFatFingersResult.adjustedPosition()), m_lastScreenPoint, MouseEventMoved, 0, LeftButton, TouchScreen); + m_webPage->handleMouseEvent(mouseMoveEvent); + + // Then send the MousePressed event. + PlatformMouseEvent mousePressedEvent(m_webPage->mapFromContentsToViewport(m_lastFatFingersResult.adjustedPosition()), m_lastScreenPoint, MouseEventPressed, 1, LeftButton, TouchScreen); + m_webPage->handleMouseEvent(mousePressedEvent); + } +} + +// This method filters what element will get tap-highlight'ed or not. To start with, +// we are going to highlight links (anchors with a valid href element), and elements +// whose tap highlight color value is different than the default value. +static Element* elementForTapHighlight(Element* elementUnderFatFinger) +{ + // Do not bail out right way here if there element does not have a renderer. + // It is the casefor <map> (descendent of <area>) elements. The associated <image> + // element actually has the renderer. + if (elementUnderFatFinger->renderer()) { + Color tapHighlightColor = elementUnderFatFinger->renderStyle()->tapHighlightColor(); + if (tapHighlightColor != RenderTheme::defaultTheme()->platformTapHighlightColor()) + return elementUnderFatFinger; + } + + bool isArea = elementUnderFatFinger->hasTagName(HTMLNames::areaTag); + Node* linkNode = elementUnderFatFinger->enclosingLinkEventParentOrSelf(); + if (!linkNode || !linkNode->isHTMLElement() || (!linkNode->renderer() && !isArea)) + return 0; + + ASSERT(linkNode->isLink()); + + // FatFingers class selector ensure only anchor with valid href attr value get here. + // It includes empty hrefs. + Element* highlightCandidateElement = static_cast<Element*>(linkNode); + + if (!isArea) + return highlightCandidateElement; + + HTMLAreaElement* area = static_cast<HTMLAreaElement*>(highlightCandidateElement); + HTMLImageElement* image = area->imageElement(); + if (image && image->renderer()) + return image; + + return 0; +} + +void TouchEventHandler::drawTapHighlight() +{ + Element* elementUnderFatFinger = m_lastFatFingersResult.nodeAsElementIfApplicable(); + if (!elementUnderFatFinger) + return; + + Element* element = elementForTapHighlight(elementUnderFatFinger); + if (!element) + return; + + // Get the element bounding rect in transformed coordinates so we can extract + // the focus ring relative position each rect. + RenderObject* renderer = element->renderer(); + ASSERT(renderer); + + Frame* elementFrame = element->document()->frame(); + ASSERT(elementFrame); + + FrameView* elementFrameView = elementFrame->view(); + if (!elementFrameView) + return; + + // Tell the client if the element is either in a scrollable container or in a fixed positioned container. + // On the client side, this info is being used to hide the tap highlight window on scroll. + RenderLayer* layer = m_webPage->enclosingFixedPositionedAncestorOrSelfIfFixedPositioned(renderer->enclosingLayer()); + bool shouldHideTapHighlightRightAfterScrolling = !layer->renderer()->isRenderView(); + shouldHideTapHighlightRightAfterScrolling |= !!m_webPage->m_inRegionScrollStartingNode.get(); + + IntPoint framePos(m_webPage->frameOffset(elementFrame)); + + // FIXME: We can get more precise on the <map> case by calculating the rect with HTMLAreaElement::computeRect(). + IntRect absoluteRect = renderer->absoluteClippedOverflowRect(); + absoluteRect.move(framePos.x(), framePos.y()); + + IntRect clippingRect; + if (elementFrame == m_webPage->mainFrame()) + clippingRect = IntRect(IntPoint(0, 0), elementFrameView->contentsSize()); + else + clippingRect = m_webPage->mainFrame()->view()->windowToContents(m_webPage->getRecursiveVisibleWindowRect(elementFrameView, true /*noClipToMainFrame*/)); + clippingRect = intersection(absoluteRect, clippingRect); + + Vector<FloatQuad> focusRingQuads; + renderer->absoluteFocusRingQuads(focusRingQuads); + + Platform::IntRectRegion region; + for (size_t i = 0; i < focusRingQuads.size(); ++i) { + IntRect rect = focusRingQuads[i].enclosingBoundingBox(); + rect.move(framePos.x(), framePos.y()); + IntRect clippedRect = intersection(clippingRect, rect); + clippedRect.inflate(2); + region = unionRegions(region, Platform::IntRect(clippedRect)); + } + + Color highlightColor = element->renderStyle()->tapHighlightColor(); + + m_webPage->m_client->drawTapHighlight(region, + highlightColor.red(), + highlightColor.green(), + highlightColor.blue(), + highlightColor.alpha(), + shouldHideTapHighlightRightAfterScrolling); +} + +} +} diff --git a/Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.h b/Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.h new file mode 100644 index 000000000..473fc30a2 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef TouchEventHandler_h +#define TouchEventHandler_h + +#include "ChromeClient.h" +#include "FatFingers.h" +#include "IntPoint.h" + +#include <BlackBerryPlatformTouchEvent.h> +#include <BlackBerryPlatformWindow.h> + +namespace BlackBerry { +namespace WebKit { + +class WebPagePrivate; + +class TouchEventHandler { +public: + TouchEventHandler(WebPagePrivate* webpage); + ~TouchEventHandler(); + + bool handleTouchPoint(Platform::TouchPoint&); + void touchEventCancel(); + void touchEventCancelAndClearFocusedNode(); + void touchHoldEvent(); + + bool shouldSuppressMouseDownOnTouchDown() const; + + const FatFingersResult& lastFatFingersResult() const { return m_lastFatFingersResult; } + void resetLastFatFingersResult() { m_lastFatFingersResult.reset(); } + +private: + unsigned spellCheck(Platform::TouchPoint&); + void handleFatFingerPressed(); + + void drawTapHighlight(); + +private: + WebPagePrivate* m_webPage; + + bool m_didCancelTouch; + bool m_convertTouchToMouse; + + WebCore::TouchEventMode m_existingTouchMode; + + WebCore::IntPoint m_lastScreenPoint; // Screen Position + + FatFingersResult m_lastFatFingersResult; +}; + +} +} + +#endif // TouchEventHandler_h diff --git a/Source/WebKit/blackberry/WebKitSupport/WebPageCompositor.cpp b/Source/WebKit/blackberry/WebKitSupport/WebPageCompositor.cpp new file mode 100644 index 000000000..fcbc1acff --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/WebPageCompositor.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "WebPageCompositor.h" + +#include "LayerWebKitThread.h" +#include "WebPage_p.h" + +#include <GenericTimerClient.h> +#include <ThreadTimerClient.h> + +using namespace WebCore; + +namespace BlackBerry { +namespace WebKit { + +WebPageCompositor::WebPageCompositor(WebPagePrivate* page) + : m_webPage(page) + , m_layerRenderer(LayerRenderer::create(page->m_page)) + , m_generation(0) + , m_compositedGeneration(-1) + , m_compositingOntoMainWindow(false) + , m_blitTimer(this, &BlackBerry::WebKit::WebPageCompositor::blitTimerFired) + , m_timerClient(new BlackBerry::Platform::GenericTimerClient(BlackBerry::Platform::userInterfaceThreadTimerClient())) +{ + m_blitTimer.setClient(m_timerClient); +} + +WebPageCompositor::~WebPageCompositor() +{ + m_blitTimer.stop(); + delete m_timerClient; +} + +bool WebPageCompositor::hardwareCompositing() const +{ + return m_layerRenderer->hardwareCompositing(); +} + +void WebPageCompositor::setRootLayer(LayerCompositingThread* rootLayer) +{ + m_rootLayer = rootLayer; + m_layerRenderer->setRootLayer(m_rootLayer.get()); +} + +void WebPageCompositor::setCompositingOntoMainWindow(bool compositingOntoMainWindow) +{ + m_compositingOntoMainWindow = compositingOntoMainWindow; + m_layerRenderer->setClearSurfaceOnDrawLayers(!compositingOntoMainWindow); +} + +void WebPageCompositor::commit(LayerWebKitThread* rootLayer) +{ + if (!rootLayer) + return; + + rootLayer->commitOnCompositingThread(); + ++m_generation; +} + +bool WebPageCompositor::drawLayers(const IntRect& dstRect, const FloatRect& contents) +{ + // Save a draw if we already drew this generation, for example due to a concurrent scroll operation. + if (m_compositedGeneration == m_generation && dstRect == m_compositedDstRect + && contents == m_compositedContentsRect && !m_compositingOntoMainWindow) + return false; + + m_layerRenderer->drawLayers(contents, m_layoutRectForCompositing, m_contentsSizeForCompositing, dstRect); + m_lastCompositingResults = m_layerRenderer->lastRenderingResults(); + + m_compositedDstRect = dstRect; + m_compositedContentsRect = contents; + m_compositedGeneration = m_generation; + + if (m_lastCompositingResults.needsAnimationFrame) { + ++m_generation; // The animation update moves us along one generation. + // Using a timeout of 0 actually won't start a timer, it will send a message. + m_blitTimer.start(1.0 / 60.0); + m_webPage->updateDelegatedOverlays(); + } + + return true; +} + +void WebPageCompositor::releaseLayerResources() +{ + m_layerRenderer->releaseLayerResources(); +} + +void WebPageCompositor::blitTimerFired() +{ + m_webPage->blitVisibleContents(); +} + +} // namespace WebKit +} // namespace BlackBerry + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebKit/blackberry/WebKitSupport/WebPageCompositor.h b/Source/WebKit/blackberry/WebKitSupport/WebPageCompositor.h new file mode 100644 index 000000000..437ab95e0 --- /dev/null +++ b/Source/WebKit/blackberry/WebKitSupport/WebPageCompositor.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef WebPageCompositor_h +#define WebPageCompositor_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerCompositingThread.h" +#include "LayerRenderer.h" + +#include <BlackBerryPlatformTimer.h> +#include <wtf/OwnPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { +class LayerWebKitThread; +}; + +namespace BlackBerry { +namespace WebKit { + +class WebPagePrivate; + +// This class may only be used on the compositing thread. +class WebPageCompositor { +public: + WebPageCompositor(WebPagePrivate*); + ~WebPageCompositor(); + + bool hardwareCompositing() const; + + void setRootLayer(WebCore::LayerCompositingThread*); + + void setCompositingOntoMainWindow(bool); + + void commit(WebCore::LayerWebKitThread* rootLayerProxy); + + bool drawLayers(const WebCore::IntRect& dstRect, const WebCore::FloatRect& contents); + + WebCore::IntRect layoutRectForCompositing() const { return m_layoutRectForCompositing; } + void setLayoutRectForCompositing(const WebCore::IntRect& rect) { m_layoutRectForCompositing = rect; } + + WebCore::IntSize contentsSizeForCompositing() const { return m_contentsSizeForCompositing; } + void setContentsSizeForCompositing(const WebCore::IntSize& size) { m_contentsSizeForCompositing = size; } + + WebCore::LayerRenderingResults lastCompositingResults() const { return m_lastCompositingResults; } + void setLastCompositingResults(const WebCore::LayerRenderingResults& results) { m_lastCompositingResults = results; } + + void releaseLayerResources(); + +private: + void blitTimerFired(); + + WebPagePrivate* m_webPage; + OwnPtr<WebCore::LayerRenderer> m_layerRenderer; + RefPtr<WebCore::LayerCompositingThread> m_rootLayer; + WebCore::IntRect m_layoutRectForCompositing; + WebCore::IntSize m_contentsSizeForCompositing; + WebCore::LayerRenderingResults m_lastCompositingResults; + int m_generation; + int m_compositedGeneration; + WebCore::IntRect m_compositedDstRect; + WebCore::FloatRect m_compositedContentsRect; + bool m_compositingOntoMainWindow; + BlackBerry::Platform::Timer<WebPageCompositor> m_blitTimer; + BlackBerry::Platform::TimerClient* m_timerClient; +}; + +} // namespace WebKit +} // namespace BlackBerry + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // WebPageCompositor_h diff --git a/Source/WebKit/chromium/ChangeLog b/Source/WebKit/chromium/ChangeLog index c3837d1cf..797b31c6c 100644 --- a/Source/WebKit/chromium/ChangeLog +++ b/Source/WebKit/chromium/ChangeLog @@ -1,3 +1,1562 @@ +2012-02-24 Shinya Kawanaka <shinyak@chromium.org> + + SpellCheckRequest needs to know the context where the spellcheck happened. + https://bugs.webkit.org/show_bug.cgi?id=79320 + + Reviewed by Hajime Morita. + + * src/EditorClientImpl.cpp: + (WebKit::EditorClientImpl::requestCheckingOfString): + * src/EditorClientImpl.h: + (EditorClientImpl): + * src/WebFrameImpl.cpp: + (WebKit::WebFrameImpl::requestTextChecking): + +2012-02-23 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed. Rolled DEPS. + + * DEPS: + +2012-02-23 Ian Vollick <vollick@chromium.org> + + [chromium] Implement keyframed animations for the cc thread. + https://bugs.webkit.org/show_bug.cgi?id=77229 + + Reviewed by James Robinson. + + * WebKit.gypi: + * tests/CCAnimationTestCommon.cpp: + (WebCore): + (WebCore::addOpacityTransition): + (WebKitTests::addOpacityTransitionToController): + (WebKitTests::addOpacityTransitionToLayer): + * tests/CCAnimationTestCommon.h: + (WebCore): + (WebKitTests): + * tests/CCKeyframedAnimationCurveTest.cpp: Added. + (WebCore): + (WebCore::expectTranslateX): + (WebCore::TEST): + * tests/CCLayerAnimationControllerTest.cpp: + (WebKitTests::expectTranslateX): + (WebKitTests): + (WebKitTests::TEST): + * tests/CCLayerTreeHostTest.cpp: + (WTF::CCLayerTreeHostTest::dispatchAddAnimation): + (WTF::CCLayerTreeHostTest::doBeginTest): + +2012-02-23 James Robinson <jamesr@chromium.org> + + [chromium] Clean up GraphicsContext3D initialization paths + https://bugs.webkit.org/show_bug.cgi?id=79321 + + Reviewed by Kenneth Russell. + + This simplifies the GraphicsContext3D initialization paths down to two simple codepaths, one for offscreen + contexts initialized from WebCore and one for onscreen (compositor) contexts initialized by WebViewImpl or + WebLayerTreeViewImpl. + + Offscreen initialization path: + 1) WebCore code calls WebCore::GraphicsContext3D::create(), implemented in GraphicsContext3DChromium.cpp + 2) GraphicsContext3D::create() instantiates a WebGraphicsContext3D via the static WebKitPlatformSupport interface + 3) GraphicsContext3DPrivate::createGraphicsContextFromWebContext() wraps the WebGraphicsContext3D in a + GraphicsContext3D's m_private pointer. + + Onscreen initialization path: + 1) WebViewImpl or WebLayerTreeViewImpl request an onscreen WebGraphicsContext3D from either their WebViewClient + or WebLayerTreeViewClient, respectively + 2) GraphicsContext3DPrivate::createGraphicsContextFromWebContext() wraps the WebGraphicsContext3D in a + GraphicsContext3D's m_private pointer. + + There are no other initialization paths. Specifically, we do not support instantiating onscreen contexts from + within WebCore. + + * src/GraphicsContext3DChromium.cpp: + (WebCore::GraphicsContext3DPrivate::GraphicsContext3DPrivate): + (WebCore::GraphicsContext3DPrivate::createGraphicsContextFromWebContext): + (WebCore): + (WebCore::GraphicsContext3DPrivate::platformTexture): + (WebCore::GraphicsContext3D::create): + * src/GraphicsContext3DPrivate.h: + (GraphicsContext3DPrivate): + * src/WebLayerTreeViewImpl.cpp: + (WebKit::WebLayerTreeViewImpl::createLayerTreeHostContext3D): + * src/WebViewImpl.cpp: + (std::getCompositorContextAttributes): + (WebKit::WebViewImpl::createCompositorGraphicsContext3D): + (WebKit): + (WebKit::WebViewImpl::createLayerTreeHostContext3D): + (WebKit::WebViewImpl::graphicsContext3D): + * src/WebViewImpl.h: + (WebViewImpl): + * tests/CCLayerTreeHostImplTest.cpp: + (WebKit::CCLayerTreeHostImplTest::createContext): + (CCLayerTreeHostImplTest): + (WebKit::TEST_F): + * tests/CCLayerTreeHostTest.cpp: + (WTF::MockLayerTreeHostClient::createLayerTreeHostContext3D): + * tests/Canvas2DLayerChromiumTest.cpp: + (WebCore::Canvas2DLayerChromiumTest::fullLifecycleTest): + * tests/CompositorFakeGraphicsContext3D.h: + (WebCore::createCompositorMockGraphicsContext3D): + * tests/FakeGraphicsContext3DTest.cpp: + (TEST): + +2012-02-23 Jonathan Backer <backer@chromium.org> + + [chromium] Plumb video damage to the damage tracker. + https://bugs.webkit.org/show_bug.cgi?id=79373 + + Reviewed by James Robinson. + + * src/WebMediaPlayerClientImpl.cpp: + (WebKit::WebMediaPlayerClientImpl::repaint): + +2012-02-21 James Robinson <jamesr@chromium.org> + + [chromium] Notify compositor of wheel event registration via ScrollingCoordinator + https://bugs.webkit.org/show_bug.cgi?id=79133 + + Reviewed by Dimitri Glazkov. + + Rips out old wheel event notification and adds unit tests for new LayerChromium property. + + * src/NonCompositedContentHost.cpp: + (WebKit::NonCompositedContentHost::setViewport): + * src/WebCompositorInputHandlerImpl.cpp: + (WebKit::WebCompositorInputHandlerImpl::handleInputEvent): + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::numberOfWheelEventHandlersChanged): + (WebKit::WebViewImpl::setIsAcceleratedCompositingActive): + * src/WebViewImpl.h: + * tests/CCLayerTreeHostImplTest.cpp: + (WebKit::TEST_F): + (WebKit): + * tests/LayerChromiumTest.cpp: + * tests/WebCompositorInputHandlerImplTest.cpp: + +2012-02-23 Adrienne Walker <enne@google.com> + + Unreviewed, rolling out r108666. + http://trac.webkit.org/changeset/108666 + https://bugs.webkit.org/show_bug.cgi?id=79321 + + Breaks webplugin tests: http://goo.gl/CoHIi + + * src/GraphicsContext3DChromium.cpp: + (WebCore::GraphicsContext3DPrivate::GraphicsContext3DPrivate): + (WebCore): + (WebCore::GraphicsContext3DPrivate::create): + (WebCore::GraphicsContext3DPrivate::createGraphicsContextFromWebContext): + (WebCore::GraphicsContext3DPrivate::createGraphicsContextForAnotherThread): + (WebCore::GraphicsContext3DPrivate::platformTexture): + (WebCore::GraphicsContext3D::create): + * src/GraphicsContext3DPrivate.h: + (WebKit): + (GraphicsContext3DPrivate): + * src/WebLayerTreeViewImpl.cpp: + (WebKit::WebLayerTreeViewImpl::createLayerTreeHostContext3D): + * src/WebViewImpl.cpp: + (std::getCompositorContextAttributes): + (WebKit::WebViewImpl::createLayerTreeHostContext3D): + (WebKit::WebViewImpl::graphicsContext3D): + * tests/CCLayerTreeHostImplTest.cpp: + (CCLayerTreeHostImplTest): + (WebKit::TEST_F): + * tests/CCLayerTreeHostTest.cpp: + (WTF::MockLayerTreeHostClient::createLayerTreeHostContext3D): + * tests/Canvas2DLayerChromiumTest.cpp: + (WebCore::Canvas2DLayerChromiumTest::fullLifecycleTest): + * tests/CompositorFakeGraphicsContext3D.h: + (WebCore::createCompositorMockGraphicsContext3D): + * tests/FakeGraphicsContext3DTest.cpp: + (TEST): + +2012-02-23 Daniel Sievers <sievers@chromium.org> + + [Chromium] Add video stream texture support + https://bugs.webkit.org/show_bug.cgi?id=78398 + + This upstreams the abstraction used on Android for + hardware video decoding with the compositor. + + Most of the interfaces are kept generic and the core + of this change is to allow texturing from an external + texture while receiving notifications (on the compositor + thread if we are running it) when there are new frames to + be displayed. + + Reviewed by James Robinson. + + * WebKit.gyp: + * public/WebMediaPlayer.h: + (WebKit): + (WebKit::WebMediaPlayer::setStreamTextureClient): + (WebMediaPlayer): + * public/WebStreamTextureClient.h: Copied from Source/WebKit/chromium/public/WebVideoFrame.h. + (WebKit): + (WebStreamTextureClient): + (WebKit::WebStreamTextureClient::~WebStreamTextureClient): + * public/WebVideoFrame.h: + * src/WebMediaPlayerClientImpl.cpp: + (WebKit::WebMediaPlayerClientImpl::~WebMediaPlayerClientImpl): + (WebKit::WebMediaPlayerClientImpl::setVideoFrameProviderClient): + (WebKit::WebMediaPlayerClientImpl::didReceiveFrame): + (WebKit): + (WebKit::WebMediaPlayerClientImpl::didUpdateMatrix): + * src/WebMediaPlayerClientImpl.h: + (WebMediaPlayerClientImpl): + +2012-02-22 James Robinson <jamesr@chromium.org> + + [chromium] Clean up GraphicsContext3D initialization paths + https://bugs.webkit.org/show_bug.cgi?id=79321 + + Reviewed by Kenneth Russell. + + This simplifies the GraphicsContext3D initialization paths down to two simple codepaths, one for offscreen + contexts initialized from WebCore and one for onscreen (compositor) contexts initialized by WebViewImpl or + WebLayerTreeViewImpl. + + Offscreen initialization path: + 1) WebCore code calls WebCore::GraphicsContext3D::create(), implemented in GraphicsContext3DChromium.cpp + 2) GraphicsContext3D::create() instantiates a WebGraphicsContext3D via the static WebKitPlatformSupport interface + 3) GraphicsContext3DPrivate::createGraphicsContextFromWebContext() wraps the WebGraphicsContext3D in a + GraphicsContext3D's m_private pointer. + + Onscreen initialization path: + 1) WebViewImpl or WebLayerTreeViewImpl request an onscreen WebGraphicsContext3D from either their WebViewClient + or WebLayerTreeViewClient, respectively + 2) GraphicsContext3DPrivate::createGraphicsContextFromWebContext() wraps the WebGraphicsContext3D in a + GraphicsContext3D's m_private pointer. + + There are no other initialization paths. Specifically, we do not support instantiating onscreen contexts from + within WebCore. + + * src/GraphicsContext3DChromium.cpp: + (WebCore::GraphicsContext3DPrivate::GraphicsContext3DPrivate): + (WebCore::GraphicsContext3DPrivate::createGraphicsContextFromWebContext): + (WebCore): + (WebCore::GraphicsContext3DPrivate::platformTexture): + (WebCore::GraphicsContext3D::create): + * src/GraphicsContext3DPrivate.h: + (GraphicsContext3DPrivate): + * src/WebLayerTreeViewImpl.cpp: + (WebKit::WebLayerTreeViewImpl::createLayerTreeHostContext3D): + * src/WebViewImpl.cpp: + (std::getCompositorContextAttributes): + (WebKit::WebViewImpl::createLayerTreeHostContext3D): + (WebKit::WebViewImpl::graphicsContext3D): + * tests/CCLayerTreeHostImplTest.cpp: + (WebKit::CCLayerTreeHostImplTest::createContext): + (CCLayerTreeHostImplTest): + (WebKit::TEST_F): + * tests/CCLayerTreeHostTest.cpp: + (WTF::MockLayerTreeHostClient::createLayerTreeHostContext3D): + * tests/Canvas2DLayerChromiumTest.cpp: + (WebCore::Canvas2DLayerChromiumTest::fullLifecycleTest): + * tests/CompositorFakeGraphicsContext3D.h: + (WebCore::createCompositorMockGraphicsContext3D): + * tests/FakeGraphicsContext3DTest.cpp: + (TEST): + +2012-02-23 Greg Billock <gbillock@google.com> + + Add UserGestureIndicator capability to Chromium API. + https://bugs.webkit.org/show_bug.cgi?id=77690 + + Reviewed by Darin Fisher. + + * WebKit.gyp: + * public/WebScopedUserGesture.h: Added. + * src/WebScopedUserGesture.cpp: Added. + +2012-02-23 Peter Beverloo <peter@chromium.org> + + Unreviewed, rolling out r108627 and r108630. + https://bugs.webkit.org/show_bug.cgi?id=79367 + + ffmpeg is creating issues and was just reverted upstream as well. + + * DEPS: + +2012-02-23 Peter Beverloo <peter@chromium.org> + + Unreviewed build fix. Remove the ffmpeg binary directory from the + Chromium-Windows DEPS file, following the commit done in the + Chromium repository: + http://src.chromium.org/viewvc/chrome?view=rev&revision=123123 + + * DEPS: + +2012-02-23 Peter Beverloo <peter@chromium.org> + + Unreviewed. Rolled DEPS. + + * DEPS: + +2012-02-22 Hajime Morrita <morrita@chromium.org> + + NOTIFICATIONS should be implemented as PageSupplement + https://bugs.webkit.org/show_bug.cgi?id=79052 + + Reviewed by Adam Barth. + + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::WebViewImpl): + +2012-02-22 Dana Jansens <danakj@chromium.org> + + [chromium] Add unit test for surface occlusion + https://bugs.webkit.org/show_bug.cgi?id=79302 + + Reviewed by James Robinson. + + * tests/CCOcclusionTrackerTest.cpp: + (WebCore::TEST): + (WebCore): + +2012-02-22 James Robinson <jamesr@chromium.org> + + Remove GraphicsContext3D::paintsIntoCanvasBuffer and unify WebGL and canvas 2d logic + https://bugs.webkit.org/show_bug.cgi?id=79317 + + Reviewed by Kenneth Russell. + + Remove paintsIntoCanvasBuffer() implementations. + + * src/GraphicsContext3DChromium.cpp: + (WebCore): + * src/GraphicsContext3DPrivate.h: + +2012-02-22 Yuta Kitamura <yutak@chromium.org> + + Unreviewed, rolling out r108590. + http://trac.webkit.org/changeset/108590 + + I mistakenly disabled tests even though the fix was already + in. + + * tests/CCOcclusionTrackerTest.cpp: + (WebCore::TEST): + +2012-02-22 Yuta Kitamura <yutak@chromium.org> + + [Chromium] Unreviewed. Disable two tests from CCOcclusionTrackerTest + which cause assertion failures. + + * tests/CCOcclusionTrackerTest.cpp: + (WebCore): + (WebCore::TEST): + +2012-02-22 Dana Jansens <danakj@chromium.org> + + [chromium] Fix CCOcclusionTracker unit test assertion + https://bugs.webkit.org/show_bug.cgi?id=79275 + + Reviewed by James Robinson. + + * tests/CCOcclusionTrackerTest.cpp: + (WebCore::TEST): + +2012-02-22 Ian Vollick <vollick@chromium.org> + + [chromium] Plumb from GraphicsLayer to the cc thread animation code + https://bugs.webkit.org/show_bug.cgi?id=75874 + + Reviewed by James Robinson. + + * WebKit.gypi: + * public/WebSettings.h: + * public/platform/WebLayerTreeView.h: + (WebKit::WebLayerTreeView::Settings::Settings): + (Settings): + * src/WebLayerTreeView.cpp: + (WebKit::WebLayerTreeView::Settings::operator CCSettings): + * src/WebSettingsImpl.cpp: + (WebKit::WebSettingsImpl::setThreadedAnimationEnabled): + (WebKit): + * src/WebSettingsImpl.h: + (WebSettingsImpl): + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::setIsAcceleratedCompositingActive): + * tests/CCActiveAnimationTest.cpp: + (WebCore::createActiveAnimation): + * tests/CCAnimationTestCommon.cpp: Added. + (WebKitTests): + (WebKitTests::FakeFloatAnimationCurve::FakeFloatAnimationCurve): + (WebKitTests::FakeFloatAnimationCurve::~FakeFloatAnimationCurve): + (WebKitTests::FakeFloatAnimationCurve::clone): + (WebKitTests::FakeTransformTransition::FakeTransformTransition): + (WebKitTests::FakeTransformTransition::~FakeTransformTransition): + (WebKitTests::FakeTransformTransition::getValue): + (WebKitTests::FakeTransformTransition::clone): + (WebKitTests::FakeFloatTransition::FakeFloatTransition): + (WebKitTests::FakeFloatTransition::~FakeFloatTransition): + (WebKitTests::FakeFloatTransition::getValue): + (WebKitTests::FakeLayerAnimationControllerImplClient::FakeLayerAnimationControllerImplClient): + (WebKitTests::FakeLayerAnimationControllerImplClient::~FakeLayerAnimationControllerImplClient): + (WebKitTests::FakeFloatTransition::clone): + (WebKitTests::addOpacityTransition): + * tests/CCAnimationTestCommon.h: Added. + (WebCore): + (WebKitTests): + (FakeFloatAnimationCurve): + (WebKitTests::FakeFloatAnimationCurve::duration): + (WebKitTests::FakeFloatAnimationCurve::getValue): + (FakeTransformTransition): + (WebKitTests::FakeTransformTransition::duration): + (FakeFloatTransition): + (WebKitTests::FakeFloatTransition::duration): + (FakeLayerAnimationControllerImplClient): + (WebKitTests::FakeLayerAnimationControllerImplClient::id): + (WebKitTests::FakeLayerAnimationControllerImplClient::opacity): + (WebKitTests::FakeLayerAnimationControllerImplClient::setOpacity): + (WebKitTests::FakeLayerAnimationControllerImplClient::transform): + (WebKitTests::FakeLayerAnimationControllerImplClient::setTransform): + (WebKitTests::FakeLayerAnimationControllerImplClient::bounds): + * tests/CCLayerAnimationControllerImplTest.cpp: + (WebKitTests::createActiveAnimation): + (WebKitTests::TEST): + * tests/CCLayerAnimationControllerTest.cpp: Added. + (WebKitTests): + (WebKitTests::createActiveAnimation): + (WebKitTests::TEST): + * tests/CCLayerTreeHostImplTest.cpp: + (WebKit::CCLayerTreeHostImplTest::postAnimationEventsToMainThreadOnImplThread): + * tests/CCLayerTreeHostTest.cpp: + (WTF::TestHooks::animateLayers): + (MockLayerTreeHostImpl): + (WTF::MockLayerTreeHostImpl::animateLayers): + (WTF::MockLayerTreeHost::create): + (WTF::MockLayerTreeHost::createLayerTreeHostImpl): + (WTF): + (MockLayerAnimationController): + (WTF::MockLayerAnimationController::create): + (WTF::MockLayerAnimationController::addAnimation): + (WTF::MockLayerTreeHostClient::scheduleComposite): + (WTF::CCLayerTreeHostTest::postAddAnimationToMainThread): + (CCLayerTreeHostTest): + (WTF::CCLayerTreeHostTest::dispatchAddAnimation): + (WTF::CCLayerTreeHostTest::doBeginTest): + (CCLayerTreeHostTestAddAnimation): + (WTF::CCLayerTreeHostTestAddAnimation::CCLayerTreeHostTestAddAnimation): + (WTF::CCLayerTreeHostTestAddAnimation::beginTest): + (WTF::CCLayerTreeHostTestAddAnimation::animateLayers): + (WTF::CCLayerTreeHostTestAddAnimation::afterTest): + (WTF::TEST_F): + * tests/TreeSynchronizerTest.cpp: + (FakeLayerAnimationController): + (WebKitTests::FakeLayerAnimationController::create): + (WebKitTests::FakeLayerAnimationController::synchronizedAnimations): + (WebKitTests::FakeLayerAnimationController::FakeLayerAnimationController): + (WebKitTests::FakeLayerAnimationController::synchronizeAnimations): + (WebKitTests): + (WebKitTests::TEST): + +2012-02-21 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * src/EditorClientImpl.cpp: + (WebKit::EditorClientImpl::shouldApplyStyle): + * src/EditorClientImpl.h: + (EditorClientImpl): + +2012-02-22 Daniel Cheng <dcheng@chromium.org> + + [chromium] Cleanup unused WebDragData methods after r107846 + https://bugs.webkit.org/show_bug.cgi?id=78837 + + Reviewed by Tony Chang. + + The deleted methods have been replaced by items() and setItems(). + + * public/platform/WebDragData.h: + (WebDragData): + * src/WebDragData.cpp: + (WebKit::WebDragData::addItem): Add ensureMutable() call to verify preconditions for + mutating the item store. + +2012-02-22 Tim Dresser <tdresser@chromium.org> + + CCLayerTreeHostImpl calls didDraw more frequently than willDraw + https://bugs.webkit.org/show_bug.cgi?id=79139 + + Reviewed by James Robinson. + + * tests/CCLayerTreeHostImplTest.cpp: + (WebKit::DidDrawCheckLayer::willDraw): + (DidDrawCheckLayer): + (WebKit::DidDrawCheckLayer::willDrawCalled): + (WebKit::DidDrawCheckLayer::DidDrawCheckLayer): + (WebKit::TEST_F): + (WebKit): + +2012-02-22 Dana Jansens <danakj@chromium.org> + + [Chromium] New CCOcclusionTracker class with tests + https://bugs.webkit.org/show_bug.cgi?id=78549 + + Reviewed by James Robinson. + + * WebKit.gypi: + * tests/CCLayerTreeHostCommonTest.cpp: + (WebCore): + * tests/CCOcclusionTrackerTest.cpp: Added. + (WebCore): + (WebCore::setLayerPropertiesForTesting): + (LayerChromiumWithForcedDrawsContent): + (WebCore::LayerChromiumWithForcedDrawsContent::LayerChromiumWithForcedDrawsContent): + (WebCore::LayerChromiumWithForcedDrawsContent::drawsContent): + (TestCCOcclusionTracker): + (WebCore::TestCCOcclusionTracker::occlusionInScreenSpace): + (WebCore::TestCCOcclusionTracker::occlusionInTargetSurface): + (WebCore::TestCCOcclusionTracker::setOcclusionInScreenSpace): + (WebCore::TestCCOcclusionTracker::setOcclusionInTargetSurface): + (WebCore::TEST): + +2012-02-22 Hao Zheng <zhenghao@chromium.org> + + [chromium] Build WebKit with MEDIA_STREAM disabled. + https://bugs.webkit.org/show_bug.cgi?id=79214 + + Reviewed by Kent Tamura. + + * src/UserMediaClientImpl.h: + +2012-02-20 Roland Steiner <rolandsteiner@chromium.org> + + <style scoped>: Add runtime-flag + https://bugs.webkit.org/show_bug.cgi?id=79074 + + Added a runtime-flag. + Enable default STYLE_SCOPED compile-time flag for Chromium. + + Reviewed by Dimitri Glazkov. + + * features.gypi: enable STYLE_SCOPED + * public/WebRuntimeFeatures.h: + (WebRuntimeFeatures): + * src/WebRuntimeFeatures.cpp: + (WebKit::WebRuntimeFeatures::enableStyleScoped): + (WebKit): + (WebKit::WebRuntimeFeatures::isStyleScopedEnabled): + +2012-02-22 Yuta Kitamura <yutak@chromium.org> + + Unreviewed, rolling out r108453. + http://trac.webkit.org/changeset/108453 + https://bugs.webkit.org/show_bug.cgi?id=78549 + + Broke Chromium's webkit_unit_tests. + + * WebKit.gypi: + * tests/CCLayerTreeHostCommonTest.cpp: + (WebCore::TEST): + (WebCore): + * tests/CCOcclusionTrackerTest.cpp: Removed. + +2012-02-22 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * src/EditorClientImpl.cpp: + (WebKit::EditorClientImpl::shouldApplyStyle): + * src/EditorClientImpl.h: + (EditorClientImpl): + +2012-02-22 Dana Jansens <danakj@chromium.org> + + [chromium] Cull quads outside of the scissoring damage rect + https://bugs.webkit.org/show_bug.cgi?id=79181 + + Reviewed by James Robinson. + + * tests/CCQuadCullerTest.cpp: + (WebCore::TEST): + (WebCore): + +2012-02-21 Dana Jansens <danakj@chromium.org> + + [Chromium] New CCOcclusionTracker class with tests + https://bugs.webkit.org/show_bug.cgi?id=78549 + + Reviewed by James Robinson. + + * WebKit.gypi: + * tests/CCLayerTreeHostCommonTest.cpp: + (WebCore): + * tests/CCOcclusionTrackerTest.cpp: Added. + (WebCore): + (WebCore::setLayerPropertiesForTesting): + (LayerChromiumWithForcedDrawsContent): + (WebCore::LayerChromiumWithForcedDrawsContent::LayerChromiumWithForcedDrawsContent): + (WebCore::LayerChromiumWithForcedDrawsContent::drawsContent): + (TestCCOcclusionTracker): + (WebCore::TestCCOcclusionTracker::occlusionInScreenSpace): + (WebCore::TestCCOcclusionTracker::occlusionInTargetSurface): + (WebCore::TestCCOcclusionTracker::setOcclusionInScreenSpace): + (WebCore::TestCCOcclusionTracker::setOcclusionInTargetSurface): + (WebCore::TEST): + +2012-02-21 MORITA Hajime <morrita@google.com> + + INPUT_SPEECH should be implemented as a PageSupplement. + https://bugs.webkit.org/show_bug.cgi?id=79051 + + Reviewed by Adam Barth. + + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::WebViewImpl): + +2012-02-20 MORITA Hajime <morrita@google.com> + + MEDIA_STREAM should be implemented as a PageSupplement. + https://bugs.webkit.org/show_bug.cgi?id=79050 + + Reviewed by Adam Barth. + + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::WebViewImpl): + +2012-02-21 Dana Jansens <danakj@chromium.org> + + [chromium] Painting a layer clears opaque rect in untouched tiles + https://bugs.webkit.org/show_bug.cgi?id=79157 + + Reviewed by James Robinson. + + * tests/TiledLayerChromiumTest.cpp: + (WTF::TEST): + +2012-02-21 James Robinson <jamesr@chromium.org> + + Enable ScrollingCoordinator in chromium whenever compositing is enabled + https://bugs.webkit.org/show_bug.cgi?id=79165 + + Reviewed by Adam Barth. + + * src/NonCompositedContentHost.cpp: + (WebKit::NonCompositedContentHost::setViewport): + Whenever the ScrollingCoordinator is enabled the scroll layer's position is expected to be updated + externally to RenderLayerCompositor, so set it here. + * src/WebSettingsImpl.cpp: + (WebKit::WebSettingsImpl::setAcceleratedCompositingEnabled): + +2012-02-21 Daniel Cheng <dcheng@chromium.org> + + [chromium] Fix image drag out on Chromium + https://bugs.webkit.org/show_bug.cgi?id=79158 + + Reviewed by Tony Chang. + + We constructed the WebDragData::Item for dragging out an image but never added it to the + item list. This is normally covered by the fast/events/drag-image-filename.html layout test, + but the bug wasn't caught in the original patch since the implementations in Chrome and DRT + had diverged. + + * src/WebDragData.cpp: + (WebKit::WebDragData::items): + +2012-02-21 David Grogan <dgrogan@chromium.org> + + IndexedDB: webFrame isn't threadsafe, don't use it from a worker thread + https://bugs.webkit.org/show_bug.cgi?id=78659 + + After crrev.com/121669, indexed db doesn't use the web frame for + anything if called from a web worker. + + No new tests - this check was defensive and possibly not ever + triggered. + + Reviewed by Tony Chang. + + * src/IDBFactoryBackendProxy.cpp: + (WebKit::IDBFactoryBackendProxy::openFromWorker): + +2012-02-21 Yury Semikhatsky <yurys@chromium.org> + + [V8] Web Inspector: set breakpoint/pause doesn't work when worker is in a tight loop + https://bugs.webkit.org/show_bug.cgi?id=79097 + + Worker script execution will be interrupted for dispatching inspector commands. + + Reviewed by Pavel Feldman. + + * src/WebSharedWorkerImpl.cpp: + (WebKit::WebSharedWorkerImpl::dispatchDevToolsMessage): + +2012-02-20 Peter Beverloo <peter@chromium.org> + + Unreviewed. Rolled DEPS. + + * DEPS: + +2012-02-20 Kenichi Ishibashi <bashi@chromium.org> + + [WebSocket] Add deflater/inflater classes + https://bugs.webkit.org/show_bug.cgi?id=78449 + + Add tests which ensure WebSocketDeflater/WebSocketInflater can + compress/decompress data correctly. + + Reviewed by Kent Tamura. + + * WebKit.gypi: Added zlib dependency. + * WebKitUnitTests.gyp: Ditto. + * tests/WebSocketDeflaterTest.cpp: Added. + (WebCore): + (WebCore::TEST): + +2012-02-17 Yury Semikhatsky <yurys@chromium.org> + + [Chromium] Web Inspector: terminated workers are not removed from dedicated worker list + https://bugs.webkit.org/show_bug.cgi?id=78899 + + Pass original WorkerContextProxy object to the inspector instrumentation instead + of Chromium-specific one for consistency with WorkerMessagingProxy implementation + in WebCore. + + Reviewed by Pavel Feldman. + + * src/WebWorkerClientImpl.cpp: + (WebKit::WebWorkerClientImpl::startWorkerContext): + +2012-02-18 raman Tenneti <rtenneti@chromium.org> + + Track the NPN protocol version negotiated with the server + https://bugs.webkit.org/show_bug.cgi?id=77349 + + Reviewed by Darin Fisher. + + [chromium] Added ExtraData to WebURLResponse. + + * WebKit.gypi: + * public/platform/WebURLResponse.h: + (ExtraData): + (WebKit::WebURLResponse::ExtraData::~ExtraData): + (WebURLResponse): + * src/WebURLResponse.cpp: + (WebKit::WebURLResponse::extraData): + (WebKit): + (WebKit::WebURLResponse::setExtraData): + * tests/WebURLResponseTest.cpp: Added. + (WebKit): + (TestExtraData): + (WebKit::TestExtraData::TestExtraData): + (WebKit::TestExtraData::~TestExtraData): + (WebKit::TEST): + +2012-02-17 Joshua Bell <jsbell@chromium.org> + + IndexedDB: Support overloaded methods that take IDBKey or IDBKeyRange + https://bugs.webkit.org/show_bug.cgi?id=78399 + + Implements the WebKit API for IDBObjectStore.delete(IDBKeyRange), + to exercise the overload capability. + + Reviewed by Tony Chang. + + * src/IDBObjectStoreBackendProxy.cpp: + (WebKit::IDBObjectStoreBackendProxy::deleteFunction): + (WebKit): + * src/IDBObjectStoreBackendProxy.h: + (IDBObjectStoreBackendProxy): + * src/WebIDBObjectStoreImpl.cpp: + (WebKit::WebIDBObjectStoreImpl::deleteFunction): + (WebKit): + * src/WebIDBObjectStoreImpl.h: + (WebIDBObjectStoreImpl): + +2012-02-17 Michal Mocny <mmocny@google.com> + + [chromium] GL_CHROMIUM_gpu_memory_manager extension + https://bugs.webkit.org/show_bug.cgi?id=77155 + + Reviewed by James Robinson. + + * public/platform/WebGraphicsContext3D.h: + (WebGraphicsMemoryAllocationChangedCallbackCHROMIUM): + (WebKit::WebGraphicsContext3D::WebGraphicsMemoryAllocationChangedCallbackCHROMIUM::~WebGraphicsMemoryAllocationChangedCallbackCHROMIUM): + (WebGraphicsContext3D): + (WebKit::WebGraphicsContext3D::setMemoryAllocationChangedCallbackCHROMIUM): + * src/Extensions3DChromium.cpp: + (WebCore::Extensions3DChromium::setGpuMemoryAllocationChangedCallbackCHROMIUM): + (WebCore): + * src/GraphicsContext3DChromium.cpp: + (WebCore::GraphicsContext3D::~GraphicsContext3D): + (GraphicsContext3DMemoryAllocationChangedCallbackAdapter): + (WebCore::GraphicsContext3DMemoryAllocationChangedCallbackAdapter::GraphicsContext3DMemoryAllocationChangedCallbackAdapter): + (WebCore::GraphicsContext3DMemoryAllocationChangedCallbackAdapter::~GraphicsContext3DMemoryAllocationChangedCallbackAdapter): + (WebCore::GraphicsContext3DMemoryAllocationChangedCallbackAdapter::onMemoryAllocationChanged): + (WebCore): + (WebCore::GraphicsContext3DPrivate::setGpuMemoryAllocationChangedCallbackCHROMIUM): + * src/GraphicsContext3DPrivate.h: + (WebCore): + * tests/FakeWebGraphicsContext3D.h: + (WebKit::FakeWebGraphicsContext3D::setMemoryAllocationChangedCallbackCHROMIUM): + (FakeWebGraphicsContext3D): + +2012-02-17 Mihnea Ovidenie <mihnea@adobe.com> + + CSS regions enabled by default + https://bugs.webkit.org/show_bug.cgi?id=78525 + + Reviewed by David Hyatt. + + Add a runtime preference to enable/disable regions functionality at runtime(WebKitCSSRegionsEnabled). + CSSRegions are still enabled by default. + In DRT, use layoutTestController.overridePreference("WebKitCSSRegionsEnabled", "0") to disable the css regions functionality. + + * public/WebSettings.h: + * src/WebSettingsImpl.cpp: + (WebKit::WebSettingsImpl::setExperimentalCSSRegionsEnabled): + (WebKit): + * src/WebSettingsImpl.h: + (WebSettingsImpl): + +2012-02-17 Scott Graham <scottmg@chromium.org> + + [Chromium] pack Gamepad shared memory structure + https://bugs.webkit.org/show_bug.cgi?id=78022 + + Reviewed by Darin Fisher. + + Add #pragma pack around definition of shared memory structures to + avoid differences across compilers and platforms. Add COMPILE_ASSERT + to verify expected size. + + * public/platform/WebGamepad.h: + (WebKit): + * public/platform/WebGamepads.h: + (WebKit): + +2012-02-17 Tim Dresser <tdresser@chromium.org> + + [chromium] Refactor video drawing to be more data driven + https://bugs.webkit.org/show_bug.cgi?id=76720 + + Reviewed by James Robinson. + + CCLayerTreeHostImplTest.didDrawCalledOnAllLayers ensures that + CCLayerImpl::didDraw() is called on all layers, including layers + on different render surfaces. + + * tests/CCLayerTreeHostImplTest.cpp: + (DidDrawCheckLayer): + (WebKit::DidDrawCheckLayer::create): + (WebKit::DidDrawCheckLayer::didDraw): + (WebKit::DidDrawCheckLayer::didDrawCalled): + (WebKit::DidDrawCheckLayer::DidDrawCheckLayer): + (WebKit): + (WebKit::TEST_F): + +2012-02-17 Ilya Tikhonovsky <loislo@chromium.org> + + Unreviewed, rolling out r108071. + http://trac.webkit.org/changeset/108071 + https://bugs.webkit.org/show_bug.cgi?id=77155 + + chromium-mac compilation failed + + * public/platform/WebGraphicsContext3D.h: + (WebGraphicsContext3D): + * src/Extensions3DChromium.cpp: + * src/GraphicsContext3DChromium.cpp: + (WebCore::GraphicsContext3D::~GraphicsContext3D): + * src/GraphicsContext3DPrivate.h: + (WebCore): + * tests/FakeWebGraphicsContext3D.h: + +2012-02-17 Michal Mocny <mmocny@google.com> + + [chromium] GL_CHROMIUM_gpu_memory_manager extension + https://bugs.webkit.org/show_bug.cgi?id=77155 + + Reviewed by James Robinson. + + * public/platform/WebGraphicsContext3D.h: + (WebGraphicsMemoryAllocationChangedCallbackCHROMIUM): + (WebKit::WebGraphicsContext3D::WebGraphicsMemoryAllocationChangedCallbackCHROMIUM::~WebGraphicsMemoryAllocationChangedCallbackCHROMIUM): + (WebGraphicsContext3D): + (WebKit::WebGraphicsContext3D::setMemoryAllocationChangedCallbackCHROMIUM): + * src/Extensions3DChromium.cpp: + (WebCore::Extensions3DChromium::setGpuMemoryAllocationChangedCallbackCHROMIUM): + (WebCore): + * src/GraphicsContext3DChromium.cpp: + (WebCore::GraphicsContext3D::~GraphicsContext3D): + (GraphicsContext3DMemoryAllocationChangedCallbackAdapter): + (WebCore::GraphicsContext3DMemoryAllocationChangedCallbackAdapter::GraphicsContext3DMemoryAllocationChangedCallbackAdapter): + (WebCore::GraphicsContext3DMemoryAllocationChangedCallbackAdapter::~GraphicsContext3DMemoryAllocationChangedCallbackAdapter): + (WebCore::GraphicsContext3DMemoryAllocationChangedCallbackAdapter::onMemoryAllocationChanged): + (WebCore): + (WebCore::GraphicsContext3DPrivate::setGpuMemoryAllocationChangedCallbackCHROMIUM): + * src/GraphicsContext3DPrivate.h: + (WebCore): + * tests/FakeWebGraphicsContext3D.h: + (WebKit::FakeWebGraphicsContext3D::setMemoryAllocationChangedCallbackCHROMIUM): + (FakeWebGraphicsContext3D): + +2012-02-17 Ilya Tikhonovsky <loislo@chromium.org> + + Unreviewed. Chromium DEPS roll + + * DEPS: from 122122 to 122498 + +2012-02-16 Alexandre Elias <aelias@google.com> + + [chromium] Bundle page scale factor and limits in CCLayerTreeHost + https://bugs.webkit.org/show_bug.cgi?id=78762 + + Setting page scale factor and its limits in separate methods + may cause clamping bugs if one of them makes it to the + impl thread before the other. Change the API to bundle them together, + which matches the existing impl-side interface. + + Reviewed by James Robinson. + + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::computePageScaleFactorLimits): + (WebKit::WebViewImpl::setIsAcceleratedCompositingActive): + (WebKit::WebViewImpl::updateLayerTreeViewport): + * tests/CCLayerTreeHostTest.cpp: + (WTF::CCLayerTreeHostTestStartPageScaleAnimation::applyScrollAndScale): + +2012-02-16 Varun Jain <varunjain@google.com> + + [Chromium] Add method to WebViewImpl to extract zoom/scroll params for gesture events on touch devices + https://bugs.webkit.org/show_bug.cgi?id=72909 + + Reviewed by James Robinson. + + * src/WebViewImpl.cpp: + (std): + (WebKit): + (WebKit::WebViewImpl::computeBlockBounds): + (WebKit::WebViewImpl::widenRectWithinPageBounds): + (WebKit::WebViewImpl::computeScaleAndScrollForHitRect): + * src/WebViewImpl.h: + (WebViewImpl): + * tests/WebFrameTest.cpp: + (WebKit): + (WebKit::TEST_F): + * tests/data/get_scale_for_auto_zoom_into_div_test.html: Added. + +2012-02-16 Sami Kyostila <skyostil@chromium.org> + + [chromium] LayerChromium::setNeedsDisplay does not apply contents scale correctly + https://bugs.webkit.org/show_bug.cgi?id=77464 + + Added a new unit test for TiledLayerChromium to verify its invalidation behavior when + the contents scale changes. Also enhance and existing unit test for LayerChromium to + verify the paint rectangle dimensions instead just checking that it is not empty. + + Reviewed by James Robinson. + + * tests/LayerChromiumTest.cpp: + * tests/TiledLayerChromiumTest.cpp: + (WTF::FakeTiledLayerChromium::setNeedsDisplayRect): + (FakeTiledLayerChromium): + (WTF::FakeTiledLayerChromium::lastNeedsDisplayRect): + (WTF::TEST): + (WTF): + +2012-02-16 MORITA Hajime <morrita@google.com> + + https://bugs.webkit.org/show_bug.cgi?id=78065 + [Chromium] Should eliminate WebTextCheckingResult legacy APIs + + Reviewed by Kent Tamura. + + Removed unused legacy members. + + * public/WebTextCheckingResult.h: + (WebKit::WebTextCheckingResult::WebTextCheckingResult): + (WebTextCheckingResult): + * src/AssertMatchingEnums.cpp: + +2012-02-16 Evan Martin <evan@chromium.org> + + [chromium] pull third_party/gold to fix linux build + https://bugs.webkit.org/show_bug.cgi?id=78842 + + Reviewed by Tony Chang. + + The Chrome build now depends on third_party/gold also being checked out. + + * DEPS: + +2012-02-15 Michael Nordman <michaeln@google.com> + + Fix bugs in the implementation of WebDatabase::closeDatabaseImmediately. + https://bugs.webkit.org/show_bug.cgi?id=78841 + + WebDatabase now delegates this function entirely to DatabaseTracker. + This is part of resolving http://crbug.com/98939 + + Reviewed by David Levin. + + * src/WebDatabase.cpp: + (WebKit::WebDatabase::closeDatabaseImmediately): + +2012-02-16 Dana Jansens <danakj@chromium.org> + + [Chromium] Occlusion tracking with CSS filters + https://bugs.webkit.org/show_bug.cgi?id=77498 + + Reviewed by James Robinson. + + * tests/CCLayerTreeHostTest.cpp: + (CCLayerTreeHostTestLayerOcclusionWithFilters): + (WTF::CCLayerTreeHostTestLayerOcclusionWithFilters::CCLayerTreeHostTestLayerOcclusionWithFilters): + (WTF::CCLayerTreeHostTestLayerOcclusionWithFilters::beginTest): + (WTF::CCLayerTreeHostTestLayerOcclusionWithFilters::afterTest): + (WTF): + +2012-02-16 Joshua Bell <jsbell@chromium.org> + + IndexedDB: Chromium WebKit API support for IDBObjectStore.delete(IDBKeyRange) + https://bugs.webkit.org/show_bug.cgi?id=78619 + + Add an overload to WebIDBObjectStore::deleteFunction(). First part of a two-sided patch. + + Reviewed by Darin Fisher. + + * public/WebIDBObjectStore.h: + (WebKit::WebIDBObjectStore::deleteFunction): + +2012-02-16 Dana Jansens <danakj@chromium.org> + + [chromium] Clipping/Transforms applied in wrong order in opaque paint tracking + https://bugs.webkit.org/show_bug.cgi?id=78775 + + Reviewed by Stephen White. + + * tests/PlatformContextSkiaTest.cpp: + (WebCore::TEST): + +2012-02-16 Daniel Cheng <dcheng@chromium.org> + + [chromium] Add WEBKIT_EXPORT to new WebDragData methods. + https://bugs.webkit.org/show_bug.cgi?id=78843 + + Reviewed by Tony Chang. + + * public/platform/WebDragData.h: + (WebDragData): + +2012-02-16 Viet-Trung Luu <viettrungluu@chromium.org> + + [chromium] Add method to WebPluginContainer to check if a rectangle is topmost + https://bugs.webkit.org/show_bug.cgi?id=78166 + + Reviewed by Darin Fisher. + + * public/WebPluginContainer.h: + (WebPluginContainer): + * src/WebPluginContainerImpl.cpp: + * src/WebPluginContainerImpl.h: + (WebPluginContainerImpl): + +2012-02-16 Yosifumi Inoue <yosin@chromium.org> + + Build Fix: R107894 breaks Chromium Linux Build. + https://bugs.webkit.org/show_bug.cgi?id=78790 + + WebDragDataPrivate::types, inherited from ChromiumDataObject, returns PassRef<DOMStringList> since r107894. However, WebDragData expected to get old return value type HashSet<String>. + + Reviewed by Kent Tamura. + + * src/WebDragData.cpp: + (WebKit::WebDragData::items): Use RefPtr<DOMStringList> rather than HashSet<String> for value of m_private->types(). + +2012-02-15 Sami Kyostila <skyostil@google.com> + + Enable -webkit-overflow-scrolling CSS property + https://bugs.webkit.org/show_bug.cgi?id=78664 + + Reviewed by Eric Seidel. + + * features.gypi: + +2012-02-15 Tommy Widenflycht <tommyw@google.com> + + MediaStream API: Removing SecurityContext from the embedder API + https://bugs.webkit.org/show_bug.cgi?id=73816 + + Reviewed by Darin Fisher. + + * bridge/PeerConnectionHandler.cpp: + (WebCore::PeerConnectionHandler::create): + (WebCore::PeerConnectionHandler::PeerConnectionHandler): + * bridge/PeerConnectionHandlerInternal.cpp: + (WebCore::PeerConnectionHandlerInternal::PeerConnectionHandlerInternal): + * bridge/PeerConnectionHandlerInternal.h: + (WebCore): + (PeerConnectionHandlerInternal): + * public/platform/WebPeerConnectionHandler.h: + (WebPeerConnectionHandler): + (WebKit::WebPeerConnectionHandler::initialize): + +2012-02-15 Peter Beverloo <peter@chromium.org> + + [Chromium] Roll DEPS to r122122 + https://bugs.webkit.org/show_bug.cgi?id=78754 + + Unreviewed DEPS roll. + + * DEPS: + +2012-02-01 Daniel Cheng <dcheng@chromium.org> + + [chromium] Add setter/getter to expose drag data as a list of items + https://bugs.webkit.org/show_bug.cgi?id=77125 + + This change supports the unification of the data store backing ChromiumDataObject and + DataTransferItemListChromium. ChromiumDataObject will represent dragging and clipboard data + as a list of data nodes to make it more straightforward to implement the HTML spec for + DataTransferItemList. Thus, we extend the abstraction to the webkit glue layer to + simplify the serialization/deserialization between platform-specific data and WebDragData. + The other setter/getter methods are deprecated and will be removed once the dependencies in + Chromium code are gone. + + Reviewed by Darin Fisher. + + * public/platform/WebDragData.h: + (WebKit): + (WebDragData): + * src/WebDragData.cpp: + (WebKit::WebDragData::items): + (WebKit): + (WebKit::WebDragData::setItems): + (WebKit::WebDragData::addItem): + +2012-02-15 Sadrul Habib Chowdhury <sadrul@chromium.org> + + Notify ChromeClient when touch-event handlers are installed/removed. + https://bugs.webkit.org/show_bug.cgi?id=77440 + + Reviewed by Darin Fisher and Ryosuke Niwa. + + * public/WebViewClient.h: + (WebKit::WebViewClient::numberOfTouchEventHandlersChanged): + * src/ChromeClientImpl.cpp: + (WebKit::ChromeClientImpl::numTouchEventHandlersChanged): + (WebKit): + * src/ChromeClientImpl.h: + (ChromeClientImpl): + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::numberOfTouchEventHandlersChanged): + (WebKit): + * src/WebViewImpl.h: + (WebViewImpl): + +2012-02-15 Anders Carlsson <andersca@apple.com> + + Remove ScrollableArea::handleGestureEvent + https://bugs.webkit.org/show_bug.cgi?id=78661 + + Reviewed by Adam Roben. + + Update for WebCore changes. + + * src/WebPluginContainerImpl.cpp: + * src/WebPluginContainerImpl.h: + (WebPluginContainerImpl): + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::gestureEvent): + +2012-02-14 Takashi Toyoshima <toyoshim@chromium.org> + + Provide SocketStreamHandleInternal::toWebSocketStreamHandle(SocketStreamHandle*). + https://bugs.webkit.org/show_bug.cgi?id=78581 + + Reviewed by Kent Tamura. + + Now, there is no way to convert SocketStreamHandle to + WebSocketStreamHandle. In subsequent changes, I'll use this function + in FrameLoaderClientImpl. + + * src/SocketStreamHandle.cpp: Remove SocketStreamHandleInternal class declaration. + * src/SocketStreamHandleInternal.h: Move SocketStreamHandleInternal class declaration from SocketStreamHandle.cpp to expose, and add conversion function to WebSocketStreamHandle from SocketStreamHandle. + (WebKit): + (WebCore): + (SocketStreamHandleInternal): + (WebCore::SocketStreamHandleInternal::create): + (WebCore::SocketStreamHandleInternal::toWebSocketStreamHandle): + * WebKit.gyp: Add SocketStreamHandleInternal.h entry. + +2012-02-14 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r107766. + http://trac.webkit.org/changeset/107766 + https://bugs.webkit.org/show_bug.cgi?id=78665 + + Breaks Chromium Win build (Requested by bashi1 on #webkit). + + * WebKit.gypi: + * tests/WebSocketDeflaterTest.cpp: Removed. + +2012-02-14 Kenichi Ishibashi <bashi@chromium.org> + + [WebSocket] Add extension attribute support + https://bugs.webkit.org/show_bug.cgi?id=78557 + + Add WebSocketExtensionDispatcher::acceptedExtensions() checks. + + Reviewed by Kent Tamura. + + * tests/WebSocketExtensionDispatcherTest.cpp: + (WebCore::TEST_F): + +2012-02-14 Kenichi Ishibashi <bashi@chromium.org> + + [WebSocket] Add deflater/inflater classes. + https://bugs.webkit.org/show_bug.cgi?id=78449 + + Add tests which ensure WebSocketDeflater/WebSocketInflater can + compress/decompress data correctly. + + Reviewed by Kent Tamura. + + * WebKit.gypi: + * tests/WebSocketDeflaterTest.cpp: Added. + (WebCore): + (WebCore::TEST): + +2012-02-14 Dana Jansens <danakj@chromium.org> + + [chromium] Compare filters on impl thread when setting them, and test setting in unit tests + https://bugs.webkit.org/show_bug.cgi?id=78643 + + Reviewed by James Robinson. + + * tests/CCLayerImplTest.cpp: + (WebCore::TEST): + +2012-02-14 Ramya Chandrasekaran <cramya@google.com> + + Last character display for passwords in Android. + https://bugs.webkit.org/show_bug.cgi?id=78532 + + Reviewed by Adam Barth. + + * public/WebSettings.h: + * src/WebSettingsImpl.cpp: + (WebKit::WebSettingsImpl::setPasswordEchoEnabled): + (WebKit): + (WebKit::WebSettingsImpl::setPasswordEchoDurationInSeconds): + * src/WebSettingsImpl.h: + (WebSettingsImpl): + +2012-02-14 David Reveman <reveman@chromium.org> + + [Chromium] Expose perTilePainting setting through WebLayerTreeView::Settings interface. + https://bugs.webkit.org/show_bug.cgi?id=76937 + + Reviewed by James Robinson. + + Add perTilePainting to WebLayerTreeView::Settings. + + * public/platform/WebLayerTreeView.h: + (WebKit::WebLayerTreeView::Settings::Settings): + (Settings): + * src/WebLayerTreeView.cpp: + (WebKit::WebLayerTreeView::Settings::operator CCSettings): + +2012-02-14 Vsevolod Vlasov <vsevik@chromium.org> + + Web Inspector: Make ScriptsNavigator default file selector. + https://bugs.webkit.org/show_bug.cgi?id=78349 + + Reviewed by Pavel Feldman. + + * src/js/Tests.js: + (.TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch.checkNoDuplicates): + (.TestSuite.prototype.uiSourceCodesToString_): + (.TestSuite.prototype.nonAnonymousUISourceCodes_): + (.TestSuite.prototype._scriptsAreParsed): + (.TestSuite.prototype._waitUntilScriptsAreParsed.waitForAllScripts): + (.TestSuite.prototype._waitUntilScriptsAreParsed): + +2012-02-14 Hayato Ito <hayato@chromium.org> + + Make ShadowRoot.nodeType return DOCUMENT_FRAGMENT_NODE. + https://bugs.webkit.org/show_bug.cgi?id=77514 + + Reviewed by Dimitri Glazkov. + + NodeType.SHADOW_ROOT_NODE type is finally gone. + + * src/WebPageSerializerImpl.cpp: + (WebKit::WebPageSerializerImpl::buildContentForNode): + +2012-02-14 David Reveman <reveman@chromium.org> + + [Chromium] Inconsistent initialization of CCSettings in WebLayerTreeView. + https://bugs.webkit.org/show_bug.cgi?id=76927 + + Reviewed by James Robinson. + + Remove unnecessary initialization and include maxPartialTextureUpdates + in FIXME comment. + + * src/WebLayerTreeView.cpp: + (WebKit::WebLayerTreeView::Settings::operator CCSettings): + +2012-02-14 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r107661. + http://trac.webkit.org/changeset/107661 + https://bugs.webkit.org/show_bug.cgi?id=78591 + + crash on lion/qt bots (Requested by hayato on #webkit). + + * src/WebPageSerializerImpl.cpp: + (WebKit::WebPageSerializerImpl::buildContentForNode): + +2012-02-14 Yuzhu Shen <yzshen@chromium.com> + + [chromium] Pepper plugins don't receive mouse movement information in + non-mouse-lock mode. + https://bugs.webkit.org/show_bug.cgi?id=78014 + + This change makes WebMouseEventBuilder pass along mouse movement + information properly. + + There isn't test for this change because: + - the movement information added is only used by pepper, and there + isn't any test for pepper at the WebKit side. (WebKit doesn't know + about pepper.) + - this change is trivial. It just copies two newly-added data fields + from MouseEvent to WebMouseEventBuilder during conversion. + + Reviewed by Tony Chang. + + * src/WebInputEventConversion.cpp: + (WebKit::WebMouseEventBuilder::WebMouseEventBuilder): + +2012-02-11 Nikolas Zimmermann <nzimmermann@rim.com> + + Convert svg/animations to use SMIL methods for driving the timeline + https://bugs.webkit.org/show_bug.cgi?id=78422 + + Reviewed by Dirk Schulze. + + Remove SVG animation sampling functionality provided for DRT, which no longer uses it. + Instead we switched the svg/animations tests to use SVGSVGElement.setCurrentTime. + + * public/WebFrame.h: + (WebFrame): + * src/WebFrameImpl.cpp: + * src/WebFrameImpl.h: + (WebFrameImpl): + +2012-02-13 Mihai Parparita <mihaip@chromium.org> + + [Chromium] Remove BoundObject + https://bugs.webkit.org/show_bug.cgi?id=78531 + + Reviewed by Pavel Feldman. + + Remove the BoundObject class, references to it were removed in r56999. + + * WebKit.gyp: + * src/BoundObject.cpp: Removed. + * src/BoundObject.h: Removed. + * src/WebDevToolsFrontendImpl.cpp: + +2012-02-13 W. James MacLean <wjmaclean@chromium.org> + + [chromium] Remove obsolete zoom animation pathway. + https://bugs.webkit.org/show_bug.cgi?id=78359 + + Reviewed by James Robinson. + + This patch removes dead code from the previous incarnation of zoom animation for chromium. + + * src/WebViewImpl.cpp: + +2012-02-13 Hayato Ito <hayato@chromium.org> + + Make ShadowRoot.nodeType return DOCUMENT_FRAGMENT_NODE. + https://bugs.webkit.org/show_bug.cgi?id=77514 + + Reviewed by Dimitri Glazkov. + + NodeType.SHADOW_ROOT_NODE type is finally gone. + + * src/WebPageSerializerImpl.cpp: + (WebKit::WebPageSerializerImpl::buildContentForNode): + +2012-02-13 Nico Weber <thakis@chromium.org> + + [chromium] Let WebKit::initialize call InitWebCoreSystemInterface on mac. + https://bugs.webkit.org/show_bug.cgi?id=78246 + + This allows removing a bunch of code in chromium land (https://chromiumcodereview.appspot.com/9374020/), + and helps with the component build on mac (InitWebCoreSystemInterface is not an + exported function, and it shouldn't be). + + Source/WebKit/mac/WebCoreSupport/WebSystemInterface.mm early-returns when it's + called twice, so it's safe to land this change, and remove the calls in client + code in a later CL. + + Reviewed by Darin Fisher. + + * src/WebKit.cpp: + (WebKit::initializeWithoutV8): + +2012-02-13 Yosifumi Inoue <yosin@chromium.org> + + [Forms] Use enum instead of bool for HTMLInputElement::setValue + https://bugs.webkit.org/show_bug.cgi?id=75217 + + Reviewed by Kent Tamura. + + * src/WebInputElement.cpp: + (WebKit::WebInputElement::setValue): Use enum for HTMLInputElement::setValue + +2012-02-12 Hajime Morrita <morrita@chromium.org> + + Page should have less intrusive way to associate API implementation objects. + https://bugs.webkit.org/show_bug.cgi?id=78085 + + Reviewed by Adam Barth. + + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::WebViewImpl): + +2012-02-10 David Grogan <dgrogan@chromium.org> + + Disable IndexedDB permissions check from shared workers + https://bugs.webkit.org/show_bug.cgi?id=78316 + + We want to temporarily bypass this check because it causes a crash + when called from a shared worker. We'll have to fix it before + including idb on shared workers in a release but don't want to stop + developers from testing out idb on shared workers. + + No new tests because it affects shared workers only, which aren't + testable by DRT. + + Reviewed by Tony Chang. + + * src/IDBFactoryBackendProxy.cpp: + (WebKit::IDBFactoryBackendProxy::allowIDBFromWorkerThread): + +2012-02-10 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed. Rolled DEPS. + + * DEPS: + +2012-02-09 Kenichi Ishibashi <bashi@chromium.org> + + Add WebSocket extension support + https://bugs.webkit.org/show_bug.cgi?id=78079 + + Add some tests which check WebSocketExtensions::processHeaderValue() + parses the given response correctly. + + Reviewed by Kent Tamura. + + * WebKit.gypi: + * tests/WebSocketExtensionDispatcherTest.cpp: Added. + (WebCore): + (MockWebSocketExtensionProcessor): + (WebCore::MockWebSocketExtensionProcessor::MockWebSocketExtensionProcessor): + (WebSocketExtensionDispatcherTest): + (WebCore::WebSocketExtensionDispatcherTest::WebSocketExtensionDispatcherTest): + (WebCore::WebSocketExtensionDispatcherTest::SetUp): + (WebCore::WebSocketExtensionDispatcherTest::TearDown): + (WebCore::WebSocketExtensionDispatcherTest::addMockProcessor): + (WebCore::WebSocketExtensionDispatcherTest::appendResult): + (WebCore::MockWebSocketExtensionProcessor::processResponse): + (WebCore::TEST_F): + +2012-02-09 W. James MacLean <wjmaclean@chromium.org> + + [chromium] Add support for starting page/scale animations on CC impl thread from WebViewImpl + https://bugs.webkit.org/show_bug.cgi?id=77872 + + Reviewed by James Robinson. + + Provides a pathway to invoke CCLayerTreeHostImpl::startPageScaleAnimation() from + WebViewImpl. This is intended to support scale and scroll animations, such as WebInputEvent::GestureDoubleTap. + + * src/WebViewImpl.cpp: + (WebKit): + (WebKit::WebViewImpl::startPageScaleAnimation): + * src/WebViewImpl.h: + (WebViewImpl): + * tests/CCLayerTreeHostTest.cpp: + (WTF): + (CCLayerTreeHostTestStartPageScaleAnimation): + (WTF::CCLayerTreeHostTestStartPageScaleAnimation::CCLayerTreeHostTestStartPageScaleAnimation): + (WTF::CCLayerTreeHostTestStartPageScaleAnimation::beginTest): + (WTF::CCLayerTreeHostTestStartPageScaleAnimation::requestStartPageScaleAnimation): + (WTF::CCLayerTreeHostTestStartPageScaleAnimation::drawLayersOnCCThread): + (WTF::CCLayerTreeHostTestStartPageScaleAnimation::applyScrollAndScale): + (WTF::CCLayerTreeHostTestStartPageScaleAnimation::commitCompleteOnCCThread): + (WTF::CCLayerTreeHostTestStartPageScaleAnimation::afterTest): + (WTF::TEST_F): + +2012-02-09 John Bates <jbates@google.com> + + [Chromium] Add chromium-style tracing support + https://bugs.webkit.org/show_bug.cgi?id=76885 + + Reviewed by Darin Fisher. + + This code enables WebKit trace events to pass through more data to the + chromium platform tracing API and generally to use the full tracing + API provided by chromium. + + * public/platform/WebKitPlatformSupport.h: + (WebKit::WebKitPlatformSupport::getTraceCategoryEnabledFlag): + (WebKit::WebKitPlatformSupport::addTraceEvent): + * src/PlatformSupport.cpp: + (WebCore::PlatformSupport::getTraceCategoryEnabledFlag): + (WebCore::PlatformSupport::addTraceEvent): + +2012-02-09 Jonathan Backer <backer@chromium.org> + + [chromium] Plumb setNeedsRedraw. + https://bugs.webkit.org/show_bug.cgi?id=78248 + + Reviewed by James Robinson. + + * public/platform/WebLayerTreeView.h: + (WebLayerTreeView): + * src/WebLayerTreeView.cpp: + (WebKit::WebLayerTreeView::setNeedsRedraw): + (WebKit): + +2012-02-09 Jonathan Backer <backer@chromium.org> + + [chromium] Add setNeedsRedraw to WebWidget + https://bugs.webkit.org/show_bug.cgi?id=77555 + + Reviewed by James Robinson. + + * public/WebWidget.h: + (WebWidget): + (WebKit::WebWidget::setNeedsRedraw): + * src/WebViewImpl.cpp: + (WebKit::WebViewImpl::setNeedsRedraw): + (WebKit): + * src/WebViewImpl.h: + (WebViewImpl): + 2012-02-08 Raymond Liu <raymond.liu@intel.com> Fix a typo for r107125 diff --git a/Source/WebKit/chromium/DEPS b/Source/WebKit/chromium/DEPS index 2e0adf6f0..ba422445c 100644 --- a/Source/WebKit/chromium/DEPS +++ b/Source/WebKit/chromium/DEPS @@ -32,7 +32,7 @@ vars = { 'chromium_svn': 'http://src.chromium.org/svn/trunk/src', - 'chromium_rev': '121041' + 'chromium_rev': '123353' } deps = { @@ -163,6 +163,8 @@ deps_os = { # Linux, actually. 'tools/xdisplaycheck': Var('chromium_svn')+'/tools/xdisplaycheck@'+Var('chromium_rev'), + 'third_party/gold': + From('chromium_deps', 'src/third_party/gold'), 'third_party/openssl': From('chromium_deps', 'src/third_party/openssl'), }, diff --git a/Source/WebKit/chromium/WebKit.gyp b/Source/WebKit/chromium/WebKit.gyp index 12ac1ab22..f8e58b383 100644 --- a/Source/WebKit/chromium/WebKit.gyp +++ b/Source/WebKit/chromium/WebKit.gyp @@ -232,6 +232,7 @@ 'public/WebReferrerPolicy.h', 'public/WebRegularExpression.h', 'public/WebRuntimeFeatures.h', + 'public/WebScopedUserGesture.h', 'public/WebScreenInfo.h', 'public/WebScriptController.h', 'public/WebScriptSource.h', @@ -256,6 +257,7 @@ 'public/WebStorageNamespace.h', 'public/WebStorageQuotaCallbacks.h', 'public/WebStorageQuotaType.h', + 'public/WebStreamTextureClient.h', 'public/WebTextAffinity.h', 'public/WebTextCaseSensitivity.h', 'public/WebTextCheckingCompletion.h', @@ -372,8 +374,6 @@ 'src/BackForwardListChromium.h', 'src/BlobRegistryProxy.cpp', 'src/BlobRegistryProxy.h', - 'src/BoundObject.cpp', - 'src/BoundObject.h', 'src/CCThreadImpl.cpp', 'src/CCThreadImpl.h', 'src/ChromeClientImpl.cpp', @@ -465,6 +465,7 @@ 'src/ScrollbarGroup.h', 'src/SharedWorkerRepository.cpp', 'src/SocketStreamHandle.cpp', + 'src/SocketStreamHandleInternal.h', 'src/SpeechInputClientImpl.cpp', 'src/SpeechInputClientImpl.h', 'src/StorageAreaProxy.cpp', @@ -633,6 +634,7 @@ 'src/WebRange.cpp', 'src/WebRegularExpression.cpp', 'src/WebRuntimeFeatures.cpp', + 'src/WebScopedUserGesture.cpp', 'src/WebScriptController.cpp', 'src/WebScrollbarImpl.cpp', 'src/WebScrollbarImpl.h', @@ -668,6 +670,7 @@ 'src/WebURLResponse.cpp', 'src/WebURLResponsePrivate.h', 'src/WebURLError.cpp', + 'src/WebScopedUserGesture.cpp', 'src/WebUserMediaRequest.cpp', 'src/WebViewImpl.cpp', 'src/WebViewImpl.h', diff --git a/Source/WebKit/chromium/WebKit.gypi b/Source/WebKit/chromium/WebKit.gypi index c8502f573..e91e336db 100644 --- a/Source/WebKit/chromium/WebKit.gypi +++ b/Source/WebKit/chromium/WebKit.gypi @@ -61,10 +61,14 @@ 'tests/AssociatedURLLoaderTest.cpp', 'tests/Canvas2DLayerChromiumTest.cpp', 'tests/CCActiveAnimationTest.cpp', + 'tests/CCAnimationTestCommon.cpp', + 'tests/CCAnimationTestCommon.h', 'tests/CCDamageTrackerTest.cpp', 'tests/CCDelayBasedTimeSourceTest.cpp', 'tests/CCFrameRateControllerTest.cpp', + 'tests/CCKeyframedAnimationCurveTest.cpp', 'tests/CCLayerAnimationControllerImplTest.cpp', + 'tests/CCLayerAnimationControllerTest.cpp', 'tests/CCLayerImplTest.cpp', 'tests/CCLayerIteratorTest.cpp', 'tests/CCLayerQuadTest.cpp', @@ -75,6 +79,7 @@ 'tests/CCLayerTreeHostImplTest.cpp', 'tests/CCLayerTreeHostTest.cpp', 'tests/CCLayerTreeTestCommon.h', + 'tests/CCOcclusionTrackerTest.cpp', 'tests/CCQuadCullerTest.cpp', 'tests/CCRenderSurfaceTest.cpp', 'tests/CCSchedulerStateMachineTest.cpp', @@ -118,7 +123,10 @@ 'tests/WebLayerTest.cpp', 'tests/WebPageNewSerializerTest.cpp', 'tests/WebPageSerializerTest.cpp', + 'tests/WebSocketDeflaterTest.cpp', + 'tests/WebSocketExtensionDispatcherTest.cpp', 'tests/WebURLRequestTest.cpp', + 'tests/WebURLResponseTest.cpp', 'tests/WebViewTest.cpp', ], diff --git a/Source/WebKit/chromium/WebKitUnitTests.gyp b/Source/WebKit/chromium/WebKitUnitTests.gyp index 5a98a8459..d50ad1523 100644 --- a/Source/WebKit/chromium/WebKitUnitTests.gyp +++ b/Source/WebKit/chromium/WebKitUnitTests.gyp @@ -61,6 +61,7 @@ '<(chromium_src_dir)/base/base.gyp:base', '<(chromium_src_dir)/base/base.gyp:base_i18n', '<(chromium_src_dir)/base/base.gyp:test_support_base', + '<(chromium_src_dir)/third_party/zlib/zlib.gyp:zlib', '<(chromium_src_dir)/webkit/support/webkit_support.gyp:webkit_support', '<(chromium_src_dir)/webkit/support/webkit_support.gyp:webkit_user_agent', ], diff --git a/Source/WebKit/chromium/bridge/PeerConnectionHandler.cpp b/Source/WebKit/chromium/bridge/PeerConnectionHandler.cpp index e9bd9e82d..c59b2d46c 100644 --- a/Source/WebKit/chromium/bridge/PeerConnectionHandler.cpp +++ b/Source/WebKit/chromium/bridge/PeerConnectionHandler.cpp @@ -36,17 +36,16 @@ #include "PeerConnectionHandlerClient.h" #include "PeerConnectionHandlerInternal.h" -#include "SecurityOrigin.h" namespace WebCore { -PassOwnPtr<PeerConnectionHandler> PeerConnectionHandler::create(PeerConnectionHandlerClient* client, const String& serverConfiguration, PassRefPtr<SecurityOrigin> securityOrigin) +PassOwnPtr<PeerConnectionHandler> PeerConnectionHandler::create(PeerConnectionHandlerClient* client, const String& serverConfiguration, const String& username) { - return adoptPtr(new PeerConnectionHandler(client, serverConfiguration, securityOrigin)); + return adoptPtr(new PeerConnectionHandler(client, serverConfiguration, username)); } -PeerConnectionHandler::PeerConnectionHandler(PeerConnectionHandlerClient* client, const String& serverConfiguration, PassRefPtr<SecurityOrigin> securityOrigin) - : m_private(adoptPtr(new PeerConnectionHandlerInternal(client, serverConfiguration, securityOrigin))) +PeerConnectionHandler::PeerConnectionHandler(PeerConnectionHandlerClient* client, const String& serverConfiguration, const String& username) + : m_private(adoptPtr(new PeerConnectionHandlerInternal(client, serverConfiguration, username))) { } diff --git a/Source/WebKit/chromium/bridge/PeerConnectionHandlerInternal.cpp b/Source/WebKit/chromium/bridge/PeerConnectionHandlerInternal.cpp index cfc33584a..d8f61f7f0 100644 --- a/Source/WebKit/chromium/bridge/PeerConnectionHandlerInternal.cpp +++ b/Source/WebKit/chromium/bridge/PeerConnectionHandlerInternal.cpp @@ -45,15 +45,21 @@ namespace WebCore { -PeerConnectionHandlerInternal::PeerConnectionHandlerInternal(PeerConnectionHandlerClient* client, const String& serverConfiguration, PassRefPtr<SecurityOrigin> securityOrigin) +PeerConnectionHandlerInternal::PeerConnectionHandlerInternal(PeerConnectionHandlerClient* client, const String& serverConfiguration, const String& username) : m_client(client) { ASSERT(m_client); m_webHandler = adoptPtr(WebKit::webKitPlatformSupport()->createPeerConnectionHandler(this)); // FIXME: When there is some error reporting avaliable in the PeerConnection object report // if we didn't get a WebPeerConnectionHandler instance. - if (m_webHandler) - m_webHandler->initialize(serverConfiguration, securityOrigin); + + if (m_webHandler) { + // Dual calls due to API change + m_webHandler->initialize(serverConfiguration, username); + + // DEPRECATED + m_webHandler->initialize(serverConfiguration, SecurityOrigin::createFromString(username)); + } } PeerConnectionHandlerInternal::~PeerConnectionHandlerInternal() diff --git a/Source/WebKit/chromium/bridge/PeerConnectionHandlerInternal.h b/Source/WebKit/chromium/bridge/PeerConnectionHandlerInternal.h index a3e79e0ac..e17fd96b5 100644 --- a/Source/WebKit/chromium/bridge/PeerConnectionHandlerInternal.h +++ b/Source/WebKit/chromium/bridge/PeerConnectionHandlerInternal.h @@ -48,11 +48,10 @@ class WebMediaStreamDescriptor; namespace WebCore { class PeerConnectionHandlerClient; -class SecurityOrigin; class PeerConnectionHandlerInternal : public WebKit::WebPeerConnectionHandlerClient { public: - PeerConnectionHandlerInternal(PeerConnectionHandlerClient*, const String& serverConfiguration, PassRefPtr<SecurityOrigin>); + PeerConnectionHandlerInternal(PeerConnectionHandlerClient*, const String& serverConfiguration, const String& username); ~PeerConnectionHandlerInternal(); virtual void produceInitialOffer(const MediaStreamDescriptorVector& pendingAddStreams); diff --git a/Source/WebKit/chromium/features.gypi b/Source/WebKit/chromium/features.gypi index 4cca26795..4c46d4de4 100644 --- a/Source/WebKit/chromium/features.gypi +++ b/Source/WebKit/chromium/features.gypi @@ -73,6 +73,7 @@ 'ENABLE_MUTATION_OBSERVERS=<(enable_mutation_observers)', 'ENABLE_NOTIFICATIONS=1', 'ENABLE_ORIENTATION_EVENTS=0', + 'ENABLE_OVERFLOW_SCROLLING=1', 'ENABLE_PAGE_VISIBILITY_API=1', 'ENABLE_POINTER_LOCK=1', 'ENABLE_PROGRESS_TAG=1', @@ -84,7 +85,7 @@ 'ENABLE_SHARED_WORKERS=1', 'ENABLE_SMOOTH_SCROLLING=1', 'ENABLE_SQL_DATABASE=1', - 'ENABLE_STYLE_SCOPED=0', + 'ENABLE_STYLE_SCOPED=1', 'ENABLE_SVG=<(enable_svg)', 'ENABLE_SVG_FONTS=<(enable_svg)', 'ENABLE_TOUCH_EVENTS=<(enable_touch_events)', diff --git a/Source/WebKit/chromium/public/WebFrame.h b/Source/WebKit/chromium/public/WebFrame.h index 9574c490e..0d5406d52 100644 --- a/Source/WebKit/chromium/public/WebFrame.h +++ b/Source/WebKit/chromium/public/WebFrame.h @@ -624,12 +624,6 @@ public: // Returns true if selection.anchorNode has a marker on range from |from| with |length|. virtual bool selectionStartHasSpellingMarkerFor(int from, int length) const = 0; - // Pauses and samples an SVG animation. Returns false if there's no svg - // animation to pause. This is only for testing. - virtual bool pauseSVGAnimation(const WebString& animationId, - double time, - const WebString& elementId) = 0; - // Dumps the layer tree, used by the accelerated compositor, in // text form. This is used only by layout tests. virtual WebString layerTreeAsText(bool showDebugInfo = false) const = 0; diff --git a/Source/WebKit/chromium/public/WebIDBObjectStore.h b/Source/WebKit/chromium/public/WebIDBObjectStore.h index 6bd51f419..981f5ec7e 100644 --- a/Source/WebKit/chromium/public/WebIDBObjectStore.h +++ b/Source/WebKit/chromium/public/WebIDBObjectStore.h @@ -69,6 +69,7 @@ public: virtual void put(const WebSerializedScriptValue&, const WebIDBKey&, PutMode, WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&) { WEBKIT_ASSERT_NOT_REACHED(); } virtual void deleteFunction(const WebIDBKey&, WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&) { WEBKIT_ASSERT_NOT_REACHED(); } + virtual void deleteFunction(const WebIDBKeyRange&, WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&) { WEBKIT_ASSERT_NOT_REACHED(); } virtual void clear(WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&) { WEBKIT_ASSERT_NOT_REACHED(); } virtual WebIDBIndex* createIndex(const WebString& name, const WebString& keyPath, bool unique, bool multiEntry, const WebIDBTransaction& transaction, WebExceptionCode& ec) { diff --git a/Source/WebKit/chromium/public/WebMediaPlayer.h b/Source/WebKit/chromium/public/WebMediaPlayer.h index 9aaf1a3d0..239134963 100644 --- a/Source/WebKit/chromium/public/WebMediaPlayer.h +++ b/Source/WebKit/chromium/public/WebMediaPlayer.h @@ -40,6 +40,7 @@ namespace WebKit { class WebAudioSourceProvider; class WebAudioSourceProviderClient; class WebMediaPlayerClient; +class WebStreamTextureClient; class WebURL; struct WebRect; struct WebSize; @@ -162,6 +163,8 @@ public: // method should no longer be referenced after the call is made. virtual void putCurrentFrame(WebVideoFrame*) { } + virtual void setStreamTextureClient(WebStreamTextureClient*) { } + virtual WebAudioSourceProvider* audioSourceProvider() { return 0; } virtual bool sourceAppend(const unsigned char* data, unsigned length) { return false; } diff --git a/Source/WebKit/chromium/public/WebPluginContainer.h b/Source/WebKit/chromium/public/WebPluginContainer.h index 122c4c8df..845cb1a28 100644 --- a/Source/WebKit/chromium/public/WebPluginContainer.h +++ b/Source/WebKit/chromium/public/WebPluginContainer.h @@ -100,6 +100,10 @@ public: // Notifies that the zoom level has changed. virtual void zoomLevelChanged(double zoomLevel) = 0; + // Determines whether the given rectangle in this plugin is above all other + // content. The rectangle is in the plugin's coordinate system. + virtual bool isRectTopmost(const WebRect&) = 0; + virtual WebPlugin* plugin() = 0; virtual void setPlugin(WebPlugin*) = 0; diff --git a/Source/WebKit/chromium/public/WebRuntimeFeatures.h b/Source/WebKit/chromium/public/WebRuntimeFeatures.h index 7e29ab0db..34e3947f6 100644 --- a/Source/WebKit/chromium/public/WebRuntimeFeatures.h +++ b/Source/WebKit/chromium/public/WebRuntimeFeatures.h @@ -124,6 +124,9 @@ public: WEBKIT_EXPORT static void enableShadowDOM(bool); WEBKIT_EXPORT static bool isShadowDOMEnabled(); + WEBKIT_EXPORT static void enableStyleScoped(bool); + WEBKIT_EXPORT static bool isStyleScopedEnabled(); + private: WebRuntimeFeatures(); }; diff --git a/Source/WebKit/chromium/src/BoundObject.h b/Source/WebKit/chromium/public/WebScopedUserGesture.h index 394ff7c9e..14798f153 100644 --- a/Source/WebKit/chromium/src/BoundObject.h +++ b/Source/WebKit/chromium/public/WebScopedUserGesture.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,34 +28,33 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BoundObject_h -#define BoundObject_h +#ifndef WebScopedUserGesture_h +#define WebScopedUserGesture_h -#include <v8.h> -#include <wtf/Noncopyable.h> +#include "platform/WebPrivateOwnPtr.h" + +namespace WebCore { +class UserGestureIndicator; +} namespace WebKit { -// BoundObject is a helper class that lets you map JavaScript method calls -// directly to C++ method calls. It should be destroyed once JS object is -// built. -class BoundObject { - WTF_MAKE_NONCOPYABLE(BoundObject); +// An instance of this class, while kept alive, will indicate that we are in +// the context of a known user gesture. To use, create one, perform whatever +// actions were done under color of a known user gesture, and then delete it. +// Usually this will be done on the stack. +class WebScopedUserGesture { public: - BoundObject(v8::Handle<v8::Context> context, void* v8This, const char* objectName); - virtual ~BoundObject(); - - void addProtoFunction(const char* name, v8::InvocationCallback callback); - void build(); + WebScopedUserGesture() { initialize(); } + ~WebScopedUserGesture() { reset(); } private: - v8::HandleScope m_handleScope; - const char* m_objectName; - v8::Handle<v8::Context> m_context; - v8::Persistent<v8::FunctionTemplate> m_hostTemplate; - void* m_v8This; + WEBKIT_EXPORT void initialize(); + WEBKIT_EXPORT void reset(); + + WebPrivateOwnPtr<WebCore::UserGestureIndicator> m_indicator; }; } // namespace WebKit -#endif +#endif // WebScopedUserGesture_h diff --git a/Source/WebKit/chromium/public/WebSettings.h b/Source/WebKit/chromium/public/WebSettings.h index 25ac07523..7f1bbb0c4 100644 --- a/Source/WebKit/chromium/public/WebSettings.h +++ b/Source/WebKit/chromium/public/WebSettings.h @@ -96,6 +96,7 @@ public: virtual void setOfflineWebApplicationCacheEnabled(bool) = 0; virtual void setWebAudioEnabled(bool) = 0; virtual void setExperimentalWebGLEnabled(bool) = 0; + virtual void setExperimentalCSSRegionsEnabled(bool) = 0; virtual void setOpenGLMultisamplingEnabled(bool) = 0; virtual void setPrivilegedWebGLExtensionsEnabled(bool) = 0; virtual void setWebGLErrorsToConsoleEnabled(bool) = 0; @@ -132,6 +133,8 @@ public: virtual void setFullScreenEnabled(bool) = 0; virtual void setAllowDisplayOfInsecureContent(bool) = 0; virtual void setAllowRunningOfInsecureContent(bool) = 0; + virtual void setPasswordEchoEnabled(bool) = 0; + virtual void setPasswordEchoDurationInSeconds(double) = 0; virtual void setShouldPrintBackgrounds(bool) = 0; virtual void setEnableScrollAnimator(bool) = 0; virtual void setHixie76WebSocketProtocolEnabled(bool) = 0; @@ -139,6 +142,7 @@ public: virtual void setAcceleratedPaintingEnabled(bool) = 0; virtual void setPerTilePaintingEnabled(bool) = 0; virtual void setPartialSwapEnabled(bool) = 0; + virtual void setThreadedAnimationEnabled(bool) = 0; protected: ~WebSettings() { } diff --git a/Source/WebKit/chromium/public/WebStreamTextureClient.h b/Source/WebKit/chromium/public/WebStreamTextureClient.h new file mode 100644 index 000000000..81002fb26 --- /dev/null +++ b/Source/WebKit/chromium/public/WebStreamTextureClient.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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 + * OWNER 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 WebStreamTextureClient_h +#define WebStreamTextureClient_h + +namespace WebKit { + +class WebStreamTextureClient { +public: + virtual void didReceiveFrame() = 0; + virtual void didUpdateMatrix(const float*) = 0; + +protected: + virtual ~WebStreamTextureClient() { } +}; + +} // namespace WebKit + +#endif diff --git a/Source/WebKit/chromium/public/WebTextCheckingResult.h b/Source/WebKit/chromium/public/WebTextCheckingResult.h index 8d0a745cc..e46f48cdc 100644 --- a/Source/WebKit/chromium/public/WebTextCheckingResult.h +++ b/Source/WebKit/chromium/public/WebTextCheckingResult.h @@ -34,7 +34,6 @@ #include "WebTextCheckingType.h" #include "platform/WebCommon.h" #include "platform/WebString.h" -#include "platform/WebVector.h" namespace WebCore { struct TextCheckingResult; @@ -44,50 +43,19 @@ namespace WebKit { // A checked entry of text checking. struct WebTextCheckingResult { - // FIXME: Should be removed after we confirm Chromium does not use it. - enum Error { - ErrorSpelling = 1 << 0, - ErrorGrammar = 1 << 1 - }; - WebTextCheckingResult() : type(WebTextCheckingTypeSpelling) - , error(ErrorSpelling) - , position(0) , location(0) , length(0) { } - explicit WebTextCheckingResult(Error e, int p = 0, int l = 0) - : type(WebTextCheckingTypeSpelling) - , error(e) - , position(p) - , location(p) - , length(l) - { - if (e & ErrorSpelling) - type = WebTextCheckingTypeSpelling; - else if (e & ErrorGrammar) - type = WebTextCheckingTypeGrammar; - else - WEBKIT_ASSERT_NOT_REACHED(); - } - WebTextCheckingResult(WebTextCheckingType type, int location, int length, const WebString& replacement = WebString()) : type(type) - , error(ErrorSpelling) - , position(location) , location(location) , length(length) , replacement(replacement) { - if (type & WebTextCheckingTypeSpelling) - error = ErrorSpelling; - else if (type & WebTextCheckingTypeGrammar) - error = ErrorGrammar; - else - WEBKIT_ASSERT_NOT_REACHED(); } #if WEBKIT_IMPLEMENTATION @@ -95,8 +63,6 @@ struct WebTextCheckingResult { #endif WebTextCheckingType type; - Error error; // FIXME: Should be removed after we confirm Chromium does not use it. - int position; // FIXME: Should be removed after we confirm Chromium does not use it. int location; int length; WebString replacement; diff --git a/Source/WebKit/chromium/public/WebVideoFrame.h b/Source/WebKit/chromium/public/WebVideoFrame.h index 8e3b2cdbd..78790627d 100644 --- a/Source/WebKit/chromium/public/WebVideoFrame.h +++ b/Source/WebKit/chromium/public/WebVideoFrame.h @@ -61,6 +61,7 @@ public: virtual int stride(unsigned plane) const { return 0; } virtual const void* data(unsigned plane) const { return 0; } virtual unsigned textureId() const { return 0; } + virtual unsigned textureTarget() const { return 0; } }; } // namespace WebKit diff --git a/Source/WebKit/chromium/public/WebViewClient.h b/Source/WebKit/chromium/public/WebViewClient.h index 1b42a48a8..b656fd5ad 100644 --- a/Source/WebKit/chromium/public/WebViewClient.h +++ b/Source/WebKit/chromium/public/WebViewClient.h @@ -263,6 +263,7 @@ public: virtual void focusedNodeChanged(const WebNode&) { } virtual void numberOfWheelEventHandlersChanged(unsigned) { } + virtual void numberOfTouchEventHandlersChanged(unsigned) { } // Indicates two things: // 1) This view may have a new layout now. diff --git a/Source/WebKit/chromium/public/WebWidget.h b/Source/WebKit/chromium/public/WebWidget.h index ca160a26e..58f3fa169 100644 --- a/Source/WebKit/chromium/public/WebWidget.h +++ b/Source/WebKit/chromium/public/WebWidget.h @@ -107,6 +107,11 @@ public: // animate or layout in this case. virtual void composite(bool finish) = 0; + // Temporary method for the embedder to notify the WebWidget that the widget + // has taken damage, e.g. due to a window expose. This method will be + // removed when the WebWidget inversion patch lands --- http://crbug.com/112837 + virtual void setNeedsRedraw() { } + // Called to inform the WebWidget of a change in theme. // Implementors that cache rendered copies of widgets need to re-render // on receiving this message diff --git a/Source/WebKit/chromium/public/platform/WebDragData.h b/Source/WebKit/chromium/public/platform/WebDragData.h index 171231eca..a6c82aee1 100644 --- a/Source/WebKit/chromium/public/platform/WebDragData.h +++ b/Source/WebKit/chromium/public/platform/WebDragData.h @@ -32,7 +32,9 @@ #define WebDragData_h #include "WebCommon.h" +#include "WebData.h" #include "WebString.h" +#include "WebURL.h" #if WEBKIT_IMPLEMENTATION namespace WebCore { class ChromiumDataObject; } @@ -41,15 +43,45 @@ namespace WTF { template <typename T> class PassRefPtr; } namespace WebKit { -class WebData; class WebDragDataPrivate; -class WebURL; template <typename T> class WebVector; // Holds data that may be exchanged through a drag-n-drop operation. It is // inexpensive to copy a WebDragData object. class WebDragData { public: + struct Item { + enum StorageType { + // String data with an associated MIME type. Depending on the MIME type, there may be + // optional metadata attributes as well. + StorageTypeString, + // Stores the name of one file being dragged into the renderer. + StorageTypeFilename, + // An image being dragged out of the renderer. Contains a buffer holding the image data + // as well as the suggested name for saving the image to. + StorageTypeBinaryData, + }; + + StorageType storageType; + + // Only valid when storageType == StorageTypeString. + WebString stringType; + WebString stringData; + + // Only valid when storageType == StorageTypeFilename. + WebString filenameData; + + // Only valid when storageType == StorageTypeBinaryData. + WebData binaryData; + + // Title associated with a link when stringType == "text/uri-list". + // Filename when storageType == StorageTypeBinaryData. + WebString title; + + // Only valid when stringType == "text/html". + WebURL baseURL; + }; + ~WebDragData() { reset(); } WebDragData() : m_private(0) { } @@ -66,44 +98,9 @@ public: bool isNull() const { return !m_private; } - WEBKIT_EXPORT WebString url() const; - WEBKIT_EXPORT void setURL(const WebURL&); - - WEBKIT_EXPORT WebString urlTitle() const; - WEBKIT_EXPORT void setURLTitle(const WebString&); - - WEBKIT_EXPORT WebString downloadMetadata() const; - WEBKIT_EXPORT void setDownloadMetadata(const WebString&); - - WEBKIT_EXPORT WebString fileExtension() const; - WEBKIT_EXPORT void setFileExtension(const WebString&); - - WEBKIT_EXPORT bool containsFilenames() const; - WEBKIT_EXPORT void filenames(WebVector<WebString>&) const; - WEBKIT_EXPORT void setFilenames(const WebVector<WebString>&); - WEBKIT_EXPORT void appendToFilenames(const WebString&); - - WEBKIT_EXPORT WebString plainText() const; - WEBKIT_EXPORT void setPlainText(const WebString&); - - WEBKIT_EXPORT WebString htmlText() const; - WEBKIT_EXPORT void setHTMLText(const WebString&); - - WEBKIT_EXPORT WebURL htmlBaseURL() const; - WEBKIT_EXPORT void setHTMLBaseURL(const WebURL&); - - WEBKIT_EXPORT WebString fileContentFilename() const; - WEBKIT_EXPORT void setFileContentFilename(const WebString&); - - WEBKIT_EXPORT WebData fileContent() const; - WEBKIT_EXPORT void setFileContent(const WebData&); - - struct CustomData { - WebString type; - WebString data; - }; - WEBKIT_EXPORT WebVector<CustomData> customData() const; - WEBKIT_EXPORT void setCustomData(const WebVector<CustomData>&); + WEBKIT_EXPORT WebVector<Item> items() const; + WEBKIT_EXPORT void setItems(const WebVector<Item>&); + WEBKIT_EXPORT void addItem(const Item&); #if WEBKIT_IMPLEMENTATION WebDragData(const WTF::PassRefPtr<WebCore::ChromiumDataObject>&); diff --git a/Source/WebKit/chromium/public/platform/WebGamepad.h b/Source/WebKit/chromium/public/platform/WebGamepad.h index 71d37b3ba..788e78ba4 100644 --- a/Source/WebKit/chromium/public/platform/WebGamepad.h +++ b/Source/WebKit/chromium/public/platform/WebGamepad.h @@ -26,8 +26,14 @@ #include "WebCommon.h" +#if WEBKIT_IMPLEMENTATION +#include <wtf/Assertions.h> +#endif + namespace WebKit { +#pragma pack(push, 1) + // This structure is intentionally POD and fixed size so that it can be shared // memory between hardware polling threads and the rest of the browser. See // also WebGamepads.h. @@ -69,6 +75,12 @@ public: float buttons[buttonsLengthCap]; }; +#if WEBKIT_IMPLEMENTATION +COMPILE_ASSERT(sizeof(WebGamepad) == 465, WebGamepad_has_wrong_size); +#endif + +#pragma pack(pop) + } #endif // WebGamepad_h diff --git a/Source/WebKit/chromium/public/platform/WebGamepads.h b/Source/WebKit/chromium/public/platform/WebGamepads.h index b1cc18ef8..50e2ab208 100644 --- a/Source/WebKit/chromium/public/platform/WebGamepads.h +++ b/Source/WebKit/chromium/public/platform/WebGamepads.h @@ -26,8 +26,14 @@ #include "WebGamepad.h" +#if WEBKIT_IMPLEMENTATION +#include <wtf/Assertions.h> +#endif + namespace WebKit { +#pragma pack(push, 1) + // This structure is intentionally POD and fixed size so that it can be stored // in shared memory between hardware polling threads and the rest of the // browser. @@ -45,6 +51,12 @@ public: WebGamepad items[itemsLengthCap]; }; +#if WEBKIT_IMPLEMENTATION +COMPILE_ASSERT(sizeof(WebGamepads) == 1864, WebGamepads_has_wrong_size); +#endif + +#pragma pack(pop) + } #endif // WebGamepads_h diff --git a/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h b/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h index 57f9d7985..f13f7c44d 100644 --- a/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h +++ b/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h @@ -130,6 +130,14 @@ public: virtual ~WebGraphicsSwapBuffersCompleteCallbackCHROMIUM() { } }; + class WebGraphicsMemoryAllocationChangedCallbackCHROMIUM { + public: + virtual void onMemoryAllocationChanged(size_t gpuResourceSizeInBytes) = 0; + + protected: + virtual ~WebGraphicsMemoryAllocationChangedCallbackCHROMIUM() { } + }; + // This destructor needs to be public so that using classes can destroy instances if initialization fails. virtual ~WebGraphicsContext3D() {} @@ -151,6 +159,9 @@ public: // GL_CHROMIUM_setVisibility - Changes the visibility of the backbuffer virtual void setVisibilityCHROMIUM(bool visible) = 0; + // GL_CHROMIUM_gpu_memory_manager - sets callback to observe changes to memory allocation limits. + virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { } + // Query whether it is built on top of compliant GLES2 implementation. virtual bool isGLES2Compliant() = 0; diff --git a/Source/WebKit/chromium/public/platform/WebKitPlatformSupport.h b/Source/WebKit/chromium/public/platform/WebKitPlatformSupport.h index 54795fa48..3bf4cb43a 100644 --- a/Source/WebKit/chromium/public/platform/WebKitPlatformSupport.h +++ b/Source/WebKit/chromium/public/platform/WebKitPlatformSupport.h @@ -240,11 +240,76 @@ public: virtual void decrementStatsCounter(const char* name) { } virtual void incrementStatsCounter(const char* name) { } - // An event is identified by the pair (name, id). The extra parameter - // specifies additional data to log with the event. - virtual bool isTraceEventEnabled() const { return true; } - virtual void traceEventBegin(const char* name, void* id, const char* extra) { } - virtual void traceEventEnd(const char* name, void* id, const char* extra) { } + // Tracing ------------------------------------------------------------- + + // Get a pointer to the enabled state of the given trace category. The + // embedder can dynamically change the enabled state as trace event + // recording is started and stopped by the application. Only long-lived + // literal strings should be given as the category name. The implementation + // expects the returned pointer to be held permanently in a local static. If + // the unsigned char is non-zero, tracing is enabled. If tracing is enabled, + // addTraceEvent is expected to be called by the trace event macros. + virtual const unsigned char* getTraceCategoryEnabledFlag(const char* categoryName) { return 0; } + // Add a trace event to the platform tracing system. Depending on the actual + // enabled state, this event may be recorded or dropped. Returns + // thresholdBeginId for use in a corresponding end addTraceEvent call. + // - phase specifies the type of event: + // - BEGIN ('B'): Marks the beginning of a scoped event. + // - END ('E'): Marks the end of a scoped event. + // - INSTANT ('I'): Standalone, instantaneous event. + // - START ('S'): Marks the beginning of an asynchronous event (the end + // event can occur in a different scope or thread). The id parameter is + // used to match START/FINISH pairs. + // - FINISH ('F'): Marks the end of an asynchronous event. + // - COUNTER ('C'): Used to trace integer quantities that change over + // time. The argument values are expected to be of type int. + // - METADATA ('M'): Reserved for internal use. + // - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag. + // - name is the name of the event. Also used to match BEGIN/END and + // START/FINISH pairs. + // - id optionally allows events of the same name to be distinguished from + // each other. For example, to trace the consutruction and destruction of + // objects, specify the pointer as the id parameter. + // - numArgs specifies the number of elements in argNames, argTypes, and + // argValues. + // - argNames is the array of argument names. Use long-lived literal strings + // or specify the COPY flag. + // - argTypes is the array of argument types: + // - BOOL (1): bool + // - UINT (2): unsigned long long + // - INT (3): long long + // - DOUBLE (4): double + // - POINTER (5): void* + // - STRING (6): char* (long-lived null-terminated char* string) + // - COPY_STRING (7): char* (temporary null-terminated char* string) + // - argValues is the array of argument values. Each value is the unsigned + // long long member of a union of all supported types. + // - thresholdBeginId optionally specifies the value returned by a previous + // call to addTraceEvent with a BEGIN phase. + // - threshold is used on an END phase event in conjunction with the + // thresholdBeginId of a prior BEGIN event. The threshold is the minimum + // number of microseconds that must have passed since the BEGIN event. If + // less than threshold microseconds has passed, the BEGIN/END pair is + // dropped. + // - flags can be 0 or one or more of the following, ORed together: + // - COPY (0x1): treat all strings (name, argNames and argValues of type + // string) as temporary so that they will be copied by addTraceEvent. + // - HAS_ID (0x2): use the id argument to uniquely identify the event for + // matching with other events of the same name. + // - MANGLE_ID (0x4): specify this flag if the id parameter is the value + // of a pointer. + virtual int addTraceEvent( + char phase, + const unsigned char* categoryEnabledFlag, + const char* name, + unsigned long long id, + int numArgs, + const char** argNames, + const unsigned char* argTypes, + const unsigned long long* argValues, + int thresholdBeginId, + long long threshold, + unsigned char flags) { return -1; } // Callbacks for reporting histogram data. // CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50 would do. diff --git a/Source/WebKit/chromium/public/platform/WebLayerTreeView.h b/Source/WebKit/chromium/public/platform/WebLayerTreeView.h index 0263b3926..17a876a98 100644 --- a/Source/WebKit/chromium/public/platform/WebLayerTreeView.h +++ b/Source/WebKit/chromium/public/platform/WebLayerTreeView.h @@ -49,14 +49,18 @@ public: , showFPSCounter(false) , showPlatformLayerTree(false) , refreshRate(0) - , partialSwapEnabled(false) { } + , perTilePainting(false) + , partialSwapEnabled(false) + , threadedAnimationEnabled(false) { } bool acceleratePainting; bool compositeOffscreen; bool showFPSCounter; bool showPlatformLayerTree; double refreshRate; + bool perTilePainting; bool partialSwapEnabled; + bool threadedAnimationEnabled; #if WEBKIT_IMPLEMENTATION operator WebCore::CCSettings() const; #endif @@ -107,6 +111,8 @@ public: operator WTF::PassRefPtr<WebCore::CCLayerTreeHost>() const; #endif + WEBKIT_EXPORT void setNeedsRedraw(); + protected: WebPrivatePtr<WebCore::CCLayerTreeHost> m_private; }; diff --git a/Source/WebKit/chromium/public/platform/WebPeerConnectionHandler.h b/Source/WebKit/chromium/public/platform/WebPeerConnectionHandler.h index 7586abc03..bd2093577 100644 --- a/Source/WebKit/chromium/public/platform/WebPeerConnectionHandler.h +++ b/Source/WebKit/chromium/public/platform/WebPeerConnectionHandler.h @@ -54,7 +54,10 @@ class WebPeerConnectionHandler { public: virtual ~WebPeerConnectionHandler() { } - virtual void initialize(const WebString& serverConfiguration, const WebSecurityOrigin&) = 0; + // DEPRECATED + virtual void initialize(const WebString& serverConfiguration, const WebSecurityOrigin&) { }; + + virtual void initialize(const WebString& serverConfiguration, const WebString& username) { }; virtual void produceInitialOffer(const WebVector<WebMediaStreamDescriptor>& pendingAddStreams) = 0; virtual void handleInitialOffer(const WebString& sdp) = 0; diff --git a/Source/WebKit/chromium/public/platform/WebURLResponse.h b/Source/WebKit/chromium/public/platform/WebURLResponse.h index 8629b849c..8d53eac38 100644 --- a/Source/WebKit/chromium/public/platform/WebURLResponse.h +++ b/Source/WebKit/chromium/public/platform/WebURLResponse.h @@ -50,6 +50,11 @@ class WebURLResponsePrivate; class WebURLResponse { public: + class ExtraData { + public: + virtual ~ExtraData() { } + }; + ~WebURLResponse() { reset(); } WebURLResponse() : m_private(0) { } @@ -174,6 +179,15 @@ public: WEBKIT_EXPORT unsigned short remotePort() const; WEBKIT_EXPORT void setRemotePort(unsigned short); + // Extra data associated with the underlying resource response. Resource + // responses can be copied. If non-null, each copy of a resource response + // holds a pointer to the extra data, and the extra data pointer will be + // deleted when the last resource response is destroyed. Setting the extra + // data pointer will cause the underlying resource response to be + // dissociated from any existing non-null extra data pointer. + WEBKIT_EXPORT ExtraData* extraData() const; + WEBKIT_EXPORT void setExtraData(ExtraData*); + protected: void assign(WebURLResponsePrivate*); diff --git a/Source/WebKit/chromium/src/AssertMatchingEnums.cpp b/Source/WebKit/chromium/src/AssertMatchingEnums.cpp index a451b88a6..3f0875b53 100644 --- a/Source/WebKit/chromium/src/AssertMatchingEnums.cpp +++ b/Source/WebKit/chromium/src/AssertMatchingEnums.cpp @@ -454,9 +454,6 @@ COMPILE_ASSERT_MATCHING_ENUM(WebFileErrorPathExists, FileError::PATH_EXISTS_ERR) COMPILE_ASSERT_MATCHING_ENUM(WebGeolocationError::ErrorPermissionDenied, GeolocationError::PermissionDenied); COMPILE_ASSERT_MATCHING_ENUM(WebGeolocationError::ErrorPositionUnavailable, GeolocationError::PositionUnavailable); -COMPILE_ASSERT_MATCHING_ENUM(WebTextCheckingResult::ErrorSpelling, DocumentMarker::Spelling); -COMPILE_ASSERT_MATCHING_ENUM(WebTextCheckingResult::ErrorGrammar, DocumentMarker::Grammar); - COMPILE_ASSERT_MATCHING_ENUM(WebTextCheckingTypeSpelling, TextCheckingTypeSpelling); COMPILE_ASSERT_MATCHING_ENUM(WebTextCheckingTypeGrammar, TextCheckingTypeGrammar); COMPILE_ASSERT_MATCHING_ENUM(WebTextCheckingTypeLink, TextCheckingTypeLink); diff --git a/Source/WebKit/chromium/src/ChromeClientImpl.cpp b/Source/WebKit/chromium/src/ChromeClientImpl.cpp index fb07b4c10..45a813859 100644 --- a/Source/WebKit/chromium/src/ChromeClientImpl.cpp +++ b/Source/WebKit/chromium/src/ChromeClientImpl.cpp @@ -1018,6 +1018,11 @@ void ChromeClientImpl::numWheelEventHandlersChanged(unsigned numberOfWheelHandle m_webView->numberOfWheelEventHandlersChanged(numberOfWheelHandlers); } +void ChromeClientImpl::numTouchEventHandlersChanged(unsigned numberOfTouchHandlers) +{ + m_webView->numberOfTouchEventHandlersChanged(numberOfTouchHandlers); +} + #if ENABLE(POINTER_LOCK) bool ChromeClientImpl::requestPointerLock() { diff --git a/Source/WebKit/chromium/src/ChromeClientImpl.h b/Source/WebKit/chromium/src/ChromeClientImpl.h index 8fd2488d9..23e02ff3d 100644 --- a/Source/WebKit/chromium/src/ChromeClientImpl.h +++ b/Source/WebKit/chromium/src/ChromeClientImpl.h @@ -204,6 +204,7 @@ public: virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const; virtual void numWheelEventHandlersChanged(unsigned); + virtual void numTouchEventHandlersChanged(unsigned); #if ENABLE(POINTER_LOCK) virtual bool requestPointerLock(); diff --git a/Source/WebKit/chromium/src/EditorClientImpl.cpp b/Source/WebKit/chromium/src/EditorClientImpl.cpp index 04aa719ed..934281a29 100644 --- a/Source/WebKit/chromium/src/EditorClientImpl.cpp +++ b/Source/WebKit/chromium/src/EditorClientImpl.cpp @@ -238,13 +238,11 @@ bool EditorClientImpl::shouldChangeSelectedRange(Range* fromRange, return true; } -bool EditorClientImpl::shouldApplyStyle(CSSStyleDeclaration* style, - Range* range) +bool EditorClientImpl::shouldApplyStyle(StylePropertySet* style, Range* range) { if (m_webView->client()) { // FIXME: Pass a reference to the CSSStyleDeclaration somehow. - return m_webView->client()->shouldApplyStyle(WebString(), - WebRange(range)); + return m_webView->client()->shouldApplyStyle(WebString(), WebRange(range)); } return true; } @@ -731,10 +729,10 @@ void EditorClientImpl::checkSpellingOfString(const UChar* text, int length, *misspellingLength = spellLength; } -void EditorClientImpl::requestCheckingOfString(SpellChecker* sender, int identifier, TextCheckingTypeMask, const String& text) +void EditorClientImpl::requestCheckingOfString(SpellChecker* sender, const WebCore::TextCheckingRequest& request) { if (m_webView->spellCheckClient()) - m_webView->spellCheckClient()->requestCheckingOfText(text, new WebTextCheckingCompletionImpl(identifier, sender)); + m_webView->spellCheckClient()->requestCheckingOfText(request.text(), new WebTextCheckingCompletionImpl(request.sequence(), sender)); } String EditorClientImpl::getAutoCorrectSuggestionForMisspelledWord(const String& misspelledWord) diff --git a/Source/WebKit/chromium/src/EditorClientImpl.h b/Source/WebKit/chromium/src/EditorClientImpl.h index 2b577107c..b167b6c2d 100644 --- a/Source/WebKit/chromium/src/EditorClientImpl.h +++ b/Source/WebKit/chromium/src/EditorClientImpl.h @@ -67,7 +67,7 @@ public: virtual bool shouldDeleteRange(WebCore::Range*); virtual bool shouldChangeSelectedRange(WebCore::Range* fromRange, WebCore::Range* toRange, WebCore::EAffinity, bool stillSelecting); - virtual bool shouldApplyStyle(WebCore::CSSStyleDeclaration*, WebCore::Range*); + virtual bool shouldApplyStyle(WebCore::StylePropertySet*, WebCore::Range*); virtual bool shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*); virtual void didBeginEditing(); virtual void respondToChangedContents(); @@ -109,7 +109,7 @@ public: virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses); virtual void willSetInputMethodState(); virtual void setInputMethodState(bool enabled); - virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&); + virtual void requestCheckingOfString(WebCore::SpellChecker*, const WebCore::TextCheckingRequest&); virtual WebCore::TextCheckerClient* textChecker() { return this; } diff --git a/Source/WebKit/chromium/src/Extensions3DChromium.cpp b/Source/WebKit/chromium/src/Extensions3DChromium.cpp index ece0405ae..73397bd2b 100644 --- a/Source/WebKit/chromium/src/Extensions3DChromium.cpp +++ b/Source/WebKit/chromium/src/Extensions3DChromium.cpp @@ -107,6 +107,11 @@ void Extensions3DChromium::setVisibilityCHROMIUM(bool visibility) m_private->setVisibilityCHROMIUM(visibility); } +void Extensions3DChromium::setGpuMemoryAllocationChangedCallbackCHROMIUM(PassOwnPtr<GpuMemoryAllocationChangedCallbackCHROMIUM> callback) +{ + m_private->setGpuMemoryAllocationChangedCallbackCHROMIUM(callback); +} + Platform3DObject Extensions3DChromium::createVertexArrayOES() { return 0; diff --git a/Source/WebKit/chromium/src/GraphicsContext3DChromium.cpp b/Source/WebKit/chromium/src/GraphicsContext3DChromium.cpp index cbbf5c581..c7ac894b0 100644 --- a/Source/WebKit/chromium/src/GraphicsContext3DChromium.cpp +++ b/Source/WebKit/chromium/src/GraphicsContext3DChromium.cpp @@ -85,12 +85,11 @@ namespace WebCore { //---------------------------------------------------------------------- // GraphicsContext3DPrivate -GraphicsContext3DPrivate::GraphicsContext3DPrivate(WebKit::WebViewImpl* webViewImpl, PassOwnPtr<WebKit::WebGraphicsContext3D> webContext, GraphicsContext3D::Attributes attrs) +GraphicsContext3DPrivate::GraphicsContext3DPrivate(PassOwnPtr<WebKit::WebGraphicsContext3D> webContext, bool preserveDrawingBuffer) : m_impl(webContext) - , m_webViewImpl(webViewImpl) , m_initializedAvailableExtensions(false) , m_layerComposited(false) - , m_preserveDrawingBuffer(attrs.preserveDrawingBuffer) + , m_preserveDrawingBuffer(preserveDrawingBuffer) , m_resourceSafety(ResourceSafetyUnknown) #if USE(SKIA) , m_grContext(0) @@ -112,59 +111,19 @@ GraphicsContext3DPrivate::~GraphicsContext3DPrivate() #endif } - -PassOwnPtr<GraphicsContext3DPrivate> GraphicsContext3DPrivate::create(WebKit::WebViewImpl* webViewImpl, PassOwnPtr<WebKit::WebGraphicsContext3D> webContext, GraphicsContext3D::Attributes attrs) -{ - return adoptPtr(new GraphicsContext3DPrivate(webViewImpl, webContext, attrs)); -} - -PassRefPtr<GraphicsContext3D> GraphicsContext3DPrivate::createGraphicsContextFromWebContext(PassOwnPtr<WebKit::WebGraphicsContext3D> webContext, GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle, ThreadUsage threadUsage) +PassRefPtr<GraphicsContext3D> GraphicsContext3DPrivate::createGraphicsContextFromWebContext(PassOwnPtr<WebKit::WebGraphicsContext3D> webContext, GraphicsContext3D::RenderStyle renderStyle, bool preserveDrawingBuffer) { - Chrome* chrome = static_cast<Chrome*>(hostWindow); - WebKit::WebViewImpl* webViewImpl = chrome ? static_cast<WebKit::WebViewImpl*>(chrome->client()->webView()) : 0; + bool renderDirectlyToHostWindow = renderStyle == GraphicsContext3D::RenderDirectlyToHostWindow; - OwnPtr<GraphicsContext3DPrivate> priv = GraphicsContext3DPrivate::create(webViewImpl, webContext, attrs); - if (!priv) - return 0; + RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(GraphicsContext3D::Attributes(), 0, renderDirectlyToHostWindow)); - bool renderDirectlyToHostWindow = renderStyle == GraphicsContext3D::RenderDirectlyToHostWindow; - RefPtr<GraphicsContext3D> result = adoptRef(new GraphicsContext3D(attrs, hostWindow, renderDirectlyToHostWindow)); - result->m_private = priv.release(); - return result.release(); + OwnPtr<GraphicsContext3DPrivate> priv = adoptPtr(new GraphicsContext3DPrivate(webContext, preserveDrawingBuffer)); + context->m_private = priv.release(); + return context.release(); } namespace { -PassRefPtr<GraphicsContext3D> createGraphicsContext(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle, GraphicsContext3DPrivate::ThreadUsage threadUsage) -{ - bool renderDirectlyToHostWindow = renderStyle == GraphicsContext3D::RenderDirectlyToHostWindow; - - WebKit::WebGraphicsContext3D::Attributes webAttributes; - webAttributes.alpha = attrs.alpha; - webAttributes.depth = attrs.depth; - webAttributes.stencil = attrs.stencil; - webAttributes.antialias = attrs.antialias; - webAttributes.premultipliedAlpha = attrs.premultipliedAlpha; - webAttributes.canRecoverFromContextLoss = attrs.canRecoverFromContextLoss; - webAttributes.noExtensions = attrs.noExtensions; - webAttributes.shareResources = attrs.shareResources; - webAttributes.forUseOnAnotherThread = threadUsage == GraphicsContext3DPrivate::ForUseOnAnotherThread; - - Chrome* chrome = static_cast<Chrome*>(hostWindow); - WebKit::WebViewImpl* webViewImpl = chrome ? static_cast<WebKit::WebViewImpl*>(chrome->client()->webView()) : 0; - OwnPtr<WebKit::WebGraphicsContext3D> webContext; - if (!webViewImpl || !webViewImpl->client()) { - if (renderDirectlyToHostWindow) - return 0; - webContext = adoptPtr(WebKit::webKitPlatformSupport()->createOffscreenGraphicsContext3D(webAttributes)); - } else - webContext = adoptPtr(webViewImpl->client()->createGraphicsContext3D(webAttributes, renderDirectlyToHostWindow)); - if (!webContext) - return 0; - - return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(webContext.release(), attrs, hostWindow, renderStyle, threadUsage); -} - void getDrawingParameters(DrawingBuffer* drawingBuffer, WebKit::WebGraphicsContext3D* graphicsContext3D, Platform3DObject* frameBufferId, int* width, int* height) { @@ -181,11 +140,6 @@ void getDrawingParameters(DrawingBuffer* drawingBuffer, WebKit::WebGraphicsConte } // anonymous namespace -PassRefPtr<GraphicsContext3D> GraphicsContext3DPrivate::createGraphicsContextForAnotherThread(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) -{ - return createGraphicsContext(attrs, hostWindow, renderStyle, ForUseOnAnotherThread); -} - WebKit::WebGraphicsContext3D* GraphicsContext3DPrivate::extractWebGraphicsContext3D(GraphicsContext3D* context) { if (!context) @@ -200,8 +154,6 @@ PlatformGraphicsContext3D GraphicsContext3DPrivate::platformGraphicsContext3D() Platform3DObject GraphicsContext3DPrivate::platformTexture() const { - ASSERT(m_webViewImpl); - m_impl->setParentContext(m_webViewImpl->graphicsContext3D()); return m_impl->getPlatformTextureId(); } @@ -345,13 +297,6 @@ PassRefPtr<ImageData> GraphicsContext3DPrivate::paintRenderingResultsToImageData return imageData.release(); } -bool GraphicsContext3DPrivate::paintsIntoCanvasBuffer() const -{ - // If the gpu compositor is on then skip the readback and software rendering path. - ASSERT(m_webViewImpl); - return !m_webViewImpl->isAcceleratedCompositingActive(); -} - void GraphicsContext3DPrivate::reshape(int width, int height) { if (width == m_impl->width() && height == m_impl->height()) @@ -1035,11 +980,28 @@ GraphicsContext3D::~GraphicsContext3D() m_private->setContextLostCallback(nullptr); m_private->setErrorMessageCallback(nullptr); m_private->setSwapBuffersCompleteCallbackCHROMIUM(nullptr); + m_private->setGpuMemoryAllocationChangedCallbackCHROMIUM(nullptr); } -PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) +PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow*, GraphicsContext3D::RenderStyle renderStyle) { - return createGraphicsContext(attrs, hostWindow, renderStyle, GraphicsContext3DPrivate::ForUseOnThisThread); + ASSERT(renderStyle != GraphicsContext3D::RenderDirectlyToHostWindow); + + WebKit::WebGraphicsContext3D::Attributes webAttributes; + webAttributes.alpha = attrs.alpha; + webAttributes.depth = attrs.depth; + webAttributes.stencil = attrs.stencil; + webAttributes.antialias = attrs.antialias; + webAttributes.premultipliedAlpha = attrs.premultipliedAlpha; + webAttributes.canRecoverFromContextLoss = attrs.canRecoverFromContextLoss; + webAttributes.noExtensions = attrs.noExtensions; + webAttributes.shareResources = attrs.shareResources; + + OwnPtr<WebKit::WebGraphicsContext3D> webContext = adoptPtr(WebKit::webKitPlatformSupport()->createOffscreenGraphicsContext3D(webAttributes)); + if (!webContext) + return 0; + + return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(webContext.release(), renderStyle, attrs.preserveDrawingBuffer); } PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D() const @@ -1247,11 +1209,6 @@ PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(Drawin DELEGATE_TO_INTERNAL_1R(paintCompositedResultsToCanvas, CanvasRenderingContext*, bool) -bool GraphicsContext3D::paintsIntoCanvasBuffer() const -{ - return m_private->paintsIntoCanvasBuffer(); -} - DELEGATE_TO_INTERNAL_R(createBuffer, Platform3DObject) DELEGATE_TO_INTERNAL_R(createFramebuffer, Platform3DObject) DELEGATE_TO_INTERNAL_R(createProgram, Platform3DObject) @@ -1359,6 +1316,31 @@ void GraphicsContext3DPrivate::setSwapBuffersCompleteCallbackCHROMIUM(PassOwnPtr m_impl->setSwapBuffersCompleteCallbackCHROMIUM(m_swapBuffersCompleteCallbackAdapter.get()); } +class GraphicsContext3DMemoryAllocationChangedCallbackAdapter : public WebKit::WebGraphicsContext3D::WebGraphicsMemoryAllocationChangedCallbackCHROMIUM { +public: + GraphicsContext3DMemoryAllocationChangedCallbackAdapter(PassOwnPtr<Extensions3DChromium::GpuMemoryAllocationChangedCallbackCHROMIUM> cb) + : m_memoryAllocationChangedCallback(cb) + { + } + + virtual ~GraphicsContext3DMemoryAllocationChangedCallbackAdapter() { } + + virtual void onMemoryAllocationChanged(size_t gpuResourceSizeInBytes) + { + if (m_memoryAllocationChangedCallback) + m_memoryAllocationChangedCallback->onGpuMemoryAllocationChanged(gpuResourceSizeInBytes); + } + +private: + OwnPtr<Extensions3DChromium::GpuMemoryAllocationChangedCallbackCHROMIUM> m_memoryAllocationChangedCallback; +}; + +void GraphicsContext3DPrivate::setGpuMemoryAllocationChangedCallbackCHROMIUM(PassOwnPtr<Extensions3DChromium::GpuMemoryAllocationChangedCallbackCHROMIUM> cb) +{ + m_memoryAllocationChangedCallbackAdapter = adoptPtr(new GraphicsContext3DMemoryAllocationChangedCallbackAdapter(cb)); + m_impl->setMemoryAllocationChangedCallbackCHROMIUM(m_memoryAllocationChangedCallbackAdapter.get()); +} + } // namespace WebCore #endif // ENABLE(WEBGL) diff --git a/Source/WebKit/chromium/src/GraphicsContext3DPrivate.h b/Source/WebKit/chromium/src/GraphicsContext3DPrivate.h index f2d49a132..d296eeb9b 100644 --- a/Source/WebKit/chromium/src/GraphicsContext3DPrivate.h +++ b/Source/WebKit/chromium/src/GraphicsContext3DPrivate.h @@ -41,8 +41,7 @@ class GrContext; namespace WebKit { class WebGraphicsContext3D; -class WebViewImpl; -} // namespace WebKit +} namespace WebCore { @@ -51,25 +50,14 @@ class Extensions3DChromium; class GraphicsContextLostCallbackAdapter; class GraphicsContext3DSwapBuffersCompleteCallbackAdapter; class GraphicsErrorMessageCallbackAdapter; +class GraphicsContext3DMemoryAllocationChangedCallbackAdapter; class GraphicsContext3DPrivate { public: - static PassOwnPtr<GraphicsContext3DPrivate> create(WebKit::WebViewImpl*, PassOwnPtr<WebKit::WebGraphicsContext3D>, GraphicsContext3D::Attributes); - - enum ThreadUsage { - ForUseOnThisThread, - ForUseOnAnotherThread, - }; - - // createGraphicsContextForAnotherThread is equivalent to - // GraphicsContext3D::create, but will skip making the context - // current. Callers must make the context current before using it AND check - // that the context was created successfully via ContextLost. Once made - // current on a thread, the context cannot be used on any other thread. - static PassRefPtr<GraphicsContext3D> createGraphicsContextForAnotherThread(GraphicsContext3D::Attributes, HostWindow*, GraphicsContext3D::RenderStyle); - - // Used in tests to create a GraphicsContext3D from a mocked WebGraphicsContext3D. - static PassRefPtr<GraphicsContext3D> createGraphicsContextFromWebContext(PassOwnPtr<WebKit::WebGraphicsContext3D>, GraphicsContext3D::Attributes, HostWindow*, GraphicsContext3D::RenderStyle, ThreadUsage); + // Callers must make the context current before using it AND check that the context was created successfully + // via ContextLost before using the context in any way. Once made current on a thread, the context cannot + // be used on any other thread. + static PassRefPtr<GraphicsContext3D> createGraphicsContextFromWebContext(PassOwnPtr<WebKit::WebGraphicsContext3D>, GraphicsContext3D::RenderStyle, bool preserveDrawingBuffer = false); ~GraphicsContext3DPrivate(); @@ -97,7 +85,6 @@ public: void paintRenderingResultsToCanvas(CanvasRenderingContext*, DrawingBuffer*); void paintFramebufferToCanvas(int framebuffer, int width, int height, bool premultiplyAlpha, ImageBuffer*); PassRefPtr<ImageData> paintRenderingResultsToImageData(DrawingBuffer*); - bool paintsIntoCanvasBuffer() const; bool paintCompositedResultsToCanvas(CanvasRenderingContext*); void prepareTexture(); @@ -295,6 +282,9 @@ public: // GL_CHROMIUM_set_visibility void setVisibilityCHROMIUM(bool); + // GL_CHROMIUM_gpu_memory_manager + void setGpuMemoryAllocationChangedCallbackCHROMIUM(PassOwnPtr<Extensions3DChromium::GpuMemoryAllocationChangedCallbackCHROMIUM>); + // GL_CHROMIUM_framebuffer_multisample void blitFramebufferCHROMIUM(GC3Dint srcX0, GC3Dint srcY0, GC3Dint srcX1, GC3Dint srcY1, GC3Dint dstX0, GC3Dint dstY0, GC3Dint dstX1, GC3Dint dstY1, GC3Dbitfield mask, GC3Denum filter); void renderbufferStorageMultisampleCHROMIUM(GC3Denum target, GC3Dsizei samples, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height); @@ -318,14 +308,14 @@ public: void texStorage2DEXT(GC3Denum target, GC3Dint levels, GC3Duint internalformat, GC3Dint width, GC3Dint height); private: - GraphicsContext3DPrivate(WebKit::WebViewImpl*, PassOwnPtr<WebKit::WebGraphicsContext3D>, GraphicsContext3D::Attributes); + GraphicsContext3DPrivate(PassOwnPtr<WebKit::WebGraphicsContext3D>, bool preserveDrawingBuffer); OwnPtr<WebKit::WebGraphicsContext3D> m_impl; OwnPtr<Extensions3DChromium> m_extensions; OwnPtr<GraphicsContextLostCallbackAdapter> m_contextLostCallbackAdapter; OwnPtr<GraphicsErrorMessageCallbackAdapter> m_errorMessageCallbackAdapter; OwnPtr<GraphicsContext3DSwapBuffersCompleteCallbackAdapter> m_swapBuffersCompleteCallbackAdapter; - WebKit::WebViewImpl* m_webViewImpl; + OwnPtr<GraphicsContext3DMemoryAllocationChangedCallbackAdapter> m_memoryAllocationChangedCallbackAdapter; bool m_initializedAvailableExtensions; HashSet<String> m_enabledExtensions; HashSet<String> m_requestableExtensions; diff --git a/Source/WebKit/chromium/src/IDBFactoryBackendProxy.cpp b/Source/WebKit/chromium/src/IDBFactoryBackendProxy.cpp index 99a0afae4..a1cce45b0 100755 --- a/Source/WebKit/chromium/src/IDBFactoryBackendProxy.cpp +++ b/Source/WebKit/chromium/src/IDBFactoryBackendProxy.cpp @@ -157,6 +157,12 @@ private: bool IDBFactoryBackendProxy::allowIDBFromWorkerThread(WorkerContext* workerContext, const String& name, const WebSecurityOrigin&) { + // FIXME: Bypass checking for permission so as not to block shared worker + // testing until a permissions check is implemented. This has to be fixed + // before m19 goes to beta. http://crbug.com/112855 + if (workerContext->isSharedWorkerContext()) + return true; + WebWorkerClientImpl* webWorkerClientImpl = static_cast<WebWorkerClientImpl*>(&workerContext->thread()->workerLoaderProxy()); WorkerRunLoop& runLoop = workerContext->thread()->runLoop(); @@ -181,15 +187,7 @@ void IDBFactoryBackendProxy::openFromWorker(const String& name, IDBCallbacks* ca callbacks->onError(WebIDBDatabaseError(0, "The user denied permission to access the database.")); return; } - WorkerLoaderProxy* workerLoaderProxy = &context->thread()->workerLoaderProxy(); - WebWorkerBase* webWorker = static_cast<WebWorkerBase*>(workerLoaderProxy); - WebView* webView = webWorker->view(); - if (!webView) { - // Frame is closed, worker is terminaring. - return; - } - WebFrame* webFrame = webView->mainFrame(); - m_webIDBFactory->open(name, new WebIDBCallbacksImpl(callbacks), origin, webFrame, dataDir); + m_webIDBFactory->open(name, new WebIDBCallbacksImpl(callbacks), origin, /*webFrame*/0, dataDir); #endif } diff --git a/Source/WebKit/chromium/src/IDBObjectStoreBackendProxy.cpp b/Source/WebKit/chromium/src/IDBObjectStoreBackendProxy.cpp index 71fb571d1..485487ac0 100755 --- a/Source/WebKit/chromium/src/IDBObjectStoreBackendProxy.cpp +++ b/Source/WebKit/chromium/src/IDBObjectStoreBackendProxy.cpp @@ -98,6 +98,14 @@ void IDBObjectStoreBackendProxy::deleteFunction(PassRefPtr<IDBKey> key, PassRefP m_webIDBObjectStore->deleteFunction(key, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction(), ec); } +void IDBObjectStoreBackendProxy::deleteFunction(PassRefPtr<IDBKeyRange> keyRange, PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec) +{ + // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer, + // all implementations of IDB interfaces are proxy objects. + IDBTransactionBackendProxy* transactionProxy = static_cast<IDBTransactionBackendProxy*>(transaction); + m_webIDBObjectStore->deleteFunction(keyRange, new WebIDBCallbacksImpl(callbacks), *transactionProxy->getWebIDBTransaction(), ec); +} + void IDBObjectStoreBackendProxy::clear(PassRefPtr<IDBCallbacks> callbacks, IDBTransactionBackendInterface* transaction, ExceptionCode& ec) { // The transaction pointer is guaranteed to be a pointer to a proxy object as, in the renderer, diff --git a/Source/WebKit/chromium/src/IDBObjectStoreBackendProxy.h b/Source/WebKit/chromium/src/IDBObjectStoreBackendProxy.h index 6d335635c..c19a0f0a4 100644 --- a/Source/WebKit/chromium/src/IDBObjectStoreBackendProxy.h +++ b/Source/WebKit/chromium/src/IDBObjectStoreBackendProxy.h @@ -49,6 +49,7 @@ public: virtual void get(PassRefPtr<WebCore::IDBKey>, PassRefPtr<WebCore::IDBCallbacks>, WebCore::IDBTransactionBackendInterface*, WebCore::ExceptionCode&); virtual void put(PassRefPtr<WebCore::SerializedScriptValue>, PassRefPtr<WebCore::IDBKey>, PutMode, PassRefPtr<WebCore::IDBCallbacks>, WebCore::IDBTransactionBackendInterface*, WebCore::ExceptionCode&); virtual void deleteFunction(PassRefPtr<WebCore::IDBKey>, PassRefPtr<WebCore::IDBCallbacks>, WebCore::IDBTransactionBackendInterface*, WebCore::ExceptionCode&); + virtual void deleteFunction(PassRefPtr<WebCore::IDBKeyRange>, PassRefPtr<WebCore::IDBCallbacks>, WebCore::IDBTransactionBackendInterface*, WebCore::ExceptionCode&); virtual void clear(PassRefPtr<WebCore::IDBCallbacks>, WebCore::IDBTransactionBackendInterface*, WebCore::ExceptionCode&); PassRefPtr<WebCore::IDBIndexBackendInterface> createIndex(const String& name, const String& keyPath, bool unique, bool multiEntry, WebCore::IDBTransactionBackendInterface*, WebCore::ExceptionCode&); diff --git a/Source/WebKit/chromium/src/NonCompositedContentHost.cpp b/Source/WebKit/chromium/src/NonCompositedContentHost.cpp index c9be08a84..b6b1a2294 100644 --- a/Source/WebKit/chromium/src/NonCompositedContentHost.cpp +++ b/Source/WebKit/chromium/src/NonCompositedContentHost.cpp @@ -27,6 +27,7 @@ #include "NonCompositedContentHost.h" +#include "FloatPoint.h" #include "FloatRect.h" #include "GraphicsLayer.h" #include "LayerChromium.h" @@ -103,6 +104,7 @@ void NonCompositedContentHost::setViewport(const WebCore::IntSize& viewportSize, m_viewportSize = viewportSize; scrollLayer()->setScrollPosition(scrollPosition); + scrollLayer()->setPosition(-scrollPosition); // Due to the possibility of pinch zoom, the noncomposited layer is always // assumed to be scrollable. scrollLayer()->setScrollable(true); diff --git a/Source/WebKit/chromium/src/PlatformSupport.cpp b/Source/WebKit/chromium/src/PlatformSupport.cpp index b4d479ca6..63be0245c 100644 --- a/Source/WebKit/chromium/src/PlatformSupport.cpp +++ b/Source/WebKit/chromium/src/PlatformSupport.cpp @@ -947,19 +947,24 @@ void PlatformSupport::paintThemePart( // Trace Event ---------------------------------------------------------------- -bool PlatformSupport::isTraceEventEnabled() -{ - return webKitPlatformSupport()->isTraceEventEnabled(); -} - -void PlatformSupport::traceEventBegin(const char* name, void* id, const char* extra) -{ - webKitPlatformSupport()->traceEventBegin(name, id, extra); -} - -void PlatformSupport::traceEventEnd(const char* name, void* id, const char* extra) -{ - webKitPlatformSupport()->traceEventEnd(name, id, extra); +const unsigned char* PlatformSupport::getTraceCategoryEnabledFlag(const char* categoryName) +{ + return webKitPlatformSupport()->getTraceCategoryEnabledFlag(categoryName); +} +int PlatformSupport::addTraceEvent(char phase, + const unsigned char* categoryEnabledFlag, + const char* name, + unsigned long long id, + int numArgs, + const char** argNames, + const unsigned char* argTypes, + const unsigned long long* argValues, + int thresholdBeginId, + long long threshold, + unsigned char flags) +{ + return webKitPlatformSupport()->addTraceEvent( + phase, categoryEnabledFlag, name, id, numArgs, argNames, argTypes, argValues, thresholdBeginId, threshold, flags); } // Visited Links -------------------------------------------------------------- diff --git a/Source/WebKit/chromium/src/SocketStreamHandle.cpp b/Source/WebKit/chromium/src/SocketStreamHandle.cpp index cf8aa02cd..298e733a4 100644 --- a/Source/WebKit/chromium/src/SocketStreamHandle.cpp +++ b/Source/WebKit/chromium/src/SocketStreamHandle.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2009, 2012 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -30,6 +30,7 @@ #include "config.h" #include "SocketStreamHandle.h" +#include "SocketStreamHandleInternal.h" #if ENABLE(WEB_SOCKETS) @@ -40,41 +41,12 @@ #include "WebKit.h" #include "platform/WebKitPlatformSupport.h" #include "platform/WebSocketStreamHandle.h" -#include "platform/WebSocketStreamHandleClient.h" -#include "platform/WebURL.h" #include <wtf/PassOwnPtr.h> using namespace WebKit; namespace WebCore { -class SocketStreamHandleInternal : public WebSocketStreamHandleClient { -public: - static PassOwnPtr<SocketStreamHandleInternal> create(SocketStreamHandle* handle) - { - return adoptPtr(new SocketStreamHandleInternal(handle)); - } - virtual ~SocketStreamHandleInternal(); - - void connect(const KURL&); - int send(const char*, int); - void close(); - - virtual void didOpenStream(WebSocketStreamHandle*, int); - virtual void didSendData(WebSocketStreamHandle*, int); - virtual void didReceiveData(WebSocketStreamHandle*, const WebData&); - virtual void didClose(WebSocketStreamHandle*); - virtual void didFail(WebSocketStreamHandle*, const WebSocketStreamError&); - -private: - explicit SocketStreamHandleInternal(SocketStreamHandle*); - - SocketStreamHandle* m_handle; - OwnPtr<WebSocketStreamHandle> m_socket; - int m_maxPendingSendAllowed; - int m_pendingAmountSent; -}; - SocketStreamHandleInternal::SocketStreamHandleInternal(SocketStreamHandle* handle) : m_handle(handle) , m_maxPendingSendAllowed(0) diff --git a/Source/WebKit/chromium/src/SocketStreamHandleInternal.h b/Source/WebKit/chromium/src/SocketStreamHandleInternal.h new file mode 100644 index 000000000..857b279e7 --- /dev/null +++ b/Source/WebKit/chromium/src/SocketStreamHandleInternal.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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 + * OWNER 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 SocketStreamHandleInternal_h +#define SocketStreamHandleInternal_h + +#if ENABLE(WEB_SOCKETS) + +#include "SocketStreamHandle.h" +#include "platform/WebSocketStreamHandleClient.h" +#include "platform/WebURL.h" +#include <wtf/PassOwnPtr.h> + +namespace WebKit { + +class WebData; +class WebSocketStreamError; +class WebSocketStreamHandle; + +} + +namespace WebCore { + +class SocketStreamHandleInternal : public WebKit::WebSocketStreamHandleClient { +public: + static PassOwnPtr<SocketStreamHandleInternal> create(SocketStreamHandle* handle) + { + return adoptPtr(new SocketStreamHandleInternal(handle)); + } + virtual ~SocketStreamHandleInternal(); + + void connect(const KURL&); + int send(const char*, int); + void close(); + + virtual void didOpenStream(WebKit::WebSocketStreamHandle*, int); + virtual void didSendData(WebKit::WebSocketStreamHandle*, int); + virtual void didReceiveData(WebKit::WebSocketStreamHandle*, const WebKit::WebData&); + virtual void didClose(WebKit::WebSocketStreamHandle*); + virtual void didFail(WebKit::WebSocketStreamHandle*, const WebKit::WebSocketStreamError&); + + static WebKit::WebSocketStreamHandle* toWebSocketStreamHandle(SocketStreamHandle* handle) + { + if (handle && handle->m_internal) + return handle->m_internal->m_socket.get(); + return 0; + } + +private: + explicit SocketStreamHandleInternal(SocketStreamHandle*); + + SocketStreamHandle* m_handle; + OwnPtr<WebKit::WebSocketStreamHandle> m_socket; + int m_maxPendingSendAllowed; + int m_pendingAmountSent; +}; + +} // namespace WebCore + +#endif // ENABLE(WEB_SOCKETS) + +#endif // SocketStreamHandleInternal_h diff --git a/Source/WebKit/chromium/src/UserMediaClientImpl.h b/Source/WebKit/chromium/src/UserMediaClientImpl.h index f6ab0416b..a1c6ac281 100644 --- a/Source/WebKit/chromium/src/UserMediaClientImpl.h +++ b/Source/WebKit/chromium/src/UserMediaClientImpl.h @@ -31,6 +31,8 @@ #ifndef UserMediaClientImpl_h #define UserMediaClientImpl_h +#if ENABLE(MEDIA_STREAM) + #include "MediaStreamSource.h" #include "UserMediaClient.h" #include <wtf/PassRefPtr.h> @@ -61,4 +63,6 @@ private: } // namespace WebKit +#endif // ENABLE(MEDIA_STREAM) + #endif // UserMediaClientImpl_h diff --git a/Source/WebKit/chromium/src/VideoFrameChromiumImpl.cpp b/Source/WebKit/chromium/src/VideoFrameChromiumImpl.cpp index ce389adc6..fcce939f7 100644 --- a/Source/WebKit/chromium/src/VideoFrameChromiumImpl.cpp +++ b/Source/WebKit/chromium/src/VideoFrameChromiumImpl.cpp @@ -128,4 +128,11 @@ unsigned VideoFrameChromiumImpl::textureId() const return 0; } +unsigned VideoFrameChromiumImpl::textureTarget() const +{ + if (m_webVideoFrame) + return m_webVideoFrame->textureTarget(); + return 0; +} + } // namespace WebKit diff --git a/Source/WebKit/chromium/src/VideoFrameChromiumImpl.h b/Source/WebKit/chromium/src/VideoFrameChromiumImpl.h index 446ab5f54..67920866f 100644 --- a/Source/WebKit/chromium/src/VideoFrameChromiumImpl.h +++ b/Source/WebKit/chromium/src/VideoFrameChromiumImpl.h @@ -58,6 +58,7 @@ public: virtual const WebCore::IntSize requiredTextureSize(unsigned plane) const; virtual bool hasPaddingBytes(unsigned plane) const; virtual unsigned textureId() const; + virtual unsigned textureTarget() const; private: WebVideoFrame* m_webVideoFrame; diff --git a/Source/WebKit/chromium/src/WebCompositorInputHandlerImpl.cpp b/Source/WebKit/chromium/src/WebCompositorInputHandlerImpl.cpp index 40c151dfd..397308b52 100644 --- a/Source/WebKit/chromium/src/WebCompositorInputHandlerImpl.cpp +++ b/Source/WebKit/chromium/src/WebCompositorInputHandlerImpl.cpp @@ -121,9 +121,9 @@ void WebCompositorInputHandlerImpl::handleInputEvent(const WebInputEvent& event) ASSERT(CCProxy::isImplThread()); ASSERT(m_client); - if (event.type == WebInputEvent::MouseWheel && !m_inputHandlerClient->haveWheelEventHandlers()) { + if (event.type == WebInputEvent::MouseWheel) { const WebMouseWheelEvent& wheelEvent = *static_cast<const WebMouseWheelEvent*>(&event); - CCInputHandlerClient::ScrollStatus scrollStatus = m_inputHandlerClient->scrollBegin(IntPoint(wheelEvent.x, wheelEvent.y)); + CCInputHandlerClient::ScrollStatus scrollStatus = m_inputHandlerClient->scrollBegin(IntPoint(wheelEvent.x, wheelEvent.y), CCInputHandlerClient::Wheel); switch (scrollStatus) { case CCInputHandlerClient::ScrollStarted: m_inputHandlerClient->scrollBy(IntSize(-wheelEvent.deltaX, -wheelEvent.deltaY)); @@ -143,7 +143,7 @@ void WebCompositorInputHandlerImpl::handleInputEvent(const WebInputEvent& event) m_expectScrollUpdateEnd = true; #endif const WebGestureEvent& gestureEvent = *static_cast<const WebGestureEvent*>(&event); - CCInputHandlerClient::ScrollStatus scrollStatus = m_inputHandlerClient->scrollBegin(IntPoint(gestureEvent.x, gestureEvent.y)); + CCInputHandlerClient::ScrollStatus scrollStatus = m_inputHandlerClient->scrollBegin(IntPoint(gestureEvent.x, gestureEvent.y), CCInputHandlerClient::Gesture); switch (scrollStatus) { case CCInputHandlerClient::ScrollStarted: m_scrollStarted = true; diff --git a/Source/WebKit/chromium/src/WebDatabase.cpp b/Source/WebKit/chromium/src/WebDatabase.cpp index 9545a07e0..9ea6ee9b5 100644 --- a/Source/WebKit/chromium/src/WebDatabase.cpp +++ b/Source/WebKit/chromium/src/WebDatabase.cpp @@ -122,10 +122,7 @@ void WebDatabase::resetSpaceAvailable(const WebString& originIdentifier) void WebDatabase::closeDatabaseImmediately(const WebString& originIdentifier, const WebString& databaseName) { #if ENABLE(SQL_DATABASE) - HashSet<RefPtr<AbstractDatabase> > databaseHandles; - DatabaseTracker::tracker().getOpenDatabases(originIdentifier, databaseName, &databaseHandles); - for (HashSet<RefPtr<AbstractDatabase> >::iterator it = databaseHandles.begin(); it != databaseHandles.end(); ++it) - it->get()->closeImmediately(); + DatabaseTracker::tracker().closeDatabasesImmediately(originIdentifier, databaseName); #endif } diff --git a/Source/WebKit/chromium/src/WebDevToolsFrontendImpl.cpp b/Source/WebKit/chromium/src/WebDevToolsFrontendImpl.cpp index dc126f0f5..054e5b245 100644 --- a/Source/WebKit/chromium/src/WebDevToolsFrontendImpl.cpp +++ b/Source/WebKit/chromium/src/WebDevToolsFrontendImpl.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "WebDevToolsFrontendImpl.h" -#include "BoundObject.h" #include "ContextMenuController.h" #include "ContextMenuItem.h" #include "DOMWindow.h" diff --git a/Source/WebKit/chromium/src/WebDragData.cpp b/Source/WebKit/chromium/src/WebDragData.cpp index 5c3123918..9e634340e 100644 --- a/Source/WebKit/chromium/src/WebDragData.cpp +++ b/Source/WebKit/chromium/src/WebDragData.cpp @@ -66,166 +66,88 @@ void WebDragData::assign(const WebDragData& other) assign(p); } -WebString WebDragData::url() const -{ - ASSERT(!isNull()); - bool ignoredSuccess; - return m_private->getData(mimeTypeURL, ignoredSuccess); -} - -void WebDragData::setURL(const WebURL& url) -{ - ensureMutable(); - m_private->setData(mimeTypeURL, KURL(url).string()); -} - -WebString WebDragData::urlTitle() const -{ - ASSERT(!isNull()); - return m_private->urlTitle(); -} - -void WebDragData::setURLTitle(const WebString& urlTitle) -{ - ensureMutable(); - m_private->setUrlTitle(urlTitle); -} - -WebString WebDragData::downloadMetadata() const -{ - ASSERT(!isNull()); - bool ignoredSuccess; - return m_private->getData(mimeTypeDownloadURL, ignoredSuccess); -} - -void WebDragData::setDownloadMetadata(const WebString& downloadMetadata) -{ - ensureMutable(); - m_private->setData(mimeTypeDownloadURL, downloadMetadata); -} - -WebString WebDragData::fileExtension() const -{ - ASSERT(!isNull()); - return m_private->fileExtension(); -} - -void WebDragData::setFileExtension(const WebString& fileExtension) -{ - ensureMutable(); - m_private->setFileExtension(fileExtension); -} - -bool WebDragData::containsFilenames() const -{ - ASSERT(!isNull()); - return m_private->containsFilenames(); -} - -void WebDragData::filenames(WebVector<WebString>& filenames) const -{ - ASSERT(!isNull()); - filenames = m_private->filenames(); -} - -void WebDragData::setFilenames(const WebVector<WebString>& filenames) -{ - ensureMutable(); - Vector<String> filenamesCopy; - filenamesCopy.append(filenames.data(), filenames.size()); - m_private->setFilenames(filenamesCopy); -} - -void WebDragData::appendToFilenames(const WebString& filename) -{ - ensureMutable(); - Vector<String> filenames = m_private->filenames(); - filenames.append(filename); - m_private->setFilenames(filenames); -} - -WebString WebDragData::plainText() const -{ - ASSERT(!isNull()); - bool ignoredSuccess; - return m_private->getData(mimeTypeTextPlain, ignoredSuccess); -} - -void WebDragData::setPlainText(const WebString& plainText) -{ - ensureMutable(); - m_private->setData(mimeTypeTextPlain, plainText); -} - -WebString WebDragData::htmlText() const -{ - ASSERT(!isNull()); - bool ignoredSuccess; - return m_private->getData(mimeTypeTextHTML, ignoredSuccess); -} - -void WebDragData::setHTMLText(const WebString& htmlText) -{ - ensureMutable(); - m_private->setData(mimeTypeTextHTML, htmlText); -} - -WebURL WebDragData::htmlBaseURL() const -{ - ASSERT(!isNull()); - return m_private->htmlBaseUrl(); -} - -void WebDragData::setHTMLBaseURL(const WebURL& htmlBaseURL) -{ - ensureMutable(); - m_private->setHtmlBaseUrl(htmlBaseURL); -} - -WebString WebDragData::fileContentFilename() const -{ - ASSERT(!isNull()); - return m_private->fileContentFilename(); -} - -void WebDragData::setFileContentFilename(const WebString& filename) -{ - ensureMutable(); - m_private->setFileContentFilename(filename); +WebVector<WebDragData::Item> WebDragData::items() const +{ + Vector<Item> itemList; + RefPtr<DOMStringList> types = m_private->types(); + if (types->contains(mimeTypeTextPlain)) { + Item item; + item.storageType = Item::StorageTypeString; + item.stringType = String(mimeTypeTextPlain); + bool ignored; + item.stringData = m_private->getData(mimeTypeTextPlain, ignored); + itemList.append(item); + } + if (types->contains(mimeTypeTextURIList)) { + Item item; + item.storageType = Item::StorageTypeString; + item.stringType = String(mimeTypeTextURIList); + bool ignored; + item.stringData = m_private->getData(mimeTypeURL, ignored); + item.title = m_private->urlTitle(); + itemList.append(item); + } + if (types->contains(mimeTypeTextHTML)) { + Item item; + item.storageType = Item::StorageTypeString; + item.stringType = String(mimeTypeTextHTML); + bool ignored; + item.stringData = m_private->getData(mimeTypeTextHTML, ignored); + item.baseURL = m_private->htmlBaseUrl(); + itemList.append(item); + } + if (types->contains(mimeTypeDownloadURL)) { + Item item; + item.storageType = Item::StorageTypeString; + item.stringType = String(mimeTypeDownloadURL); + bool ignored; + item.stringData = m_private->getData(mimeTypeDownloadURL, ignored); + itemList.append(item); + } + const HashMap<String, String>& customData = m_private->customData(); + for (HashMap<String, String>::const_iterator it = customData.begin(); it != customData.end(); ++it) { + Item item; + item.storageType = Item::StorageTypeString; + item.stringType = it->first; + item.stringData = it->second; + itemList.append(item); + } + if (m_private->fileContent()) { + Item item; + item.storageType = Item::StorageTypeBinaryData; + item.binaryData = m_private->fileContent(); + item.title = m_private->fileContentFilename(); + itemList.append(item); + } + // We don't handle filenames here, since they are never used for dragging out. + return itemList; } -WebData WebDragData::fileContent() const +void WebDragData::setItems(const WebVector<Item>& itemList) { - ASSERT(!isNull()); - return WebData(m_private->fileContent()); + m_private->clearAll(); + for (size_t i = 0; i < itemList.size(); ++i) + addItem(itemList[i]); } -void WebDragData::setFileContent(const WebData& fileContent) +void WebDragData::addItem(const Item& item) { ensureMutable(); - m_private->setFileContent(fileContent); -} - -WebVector<WebDragData::CustomData> WebDragData::customData() const -{ - ASSERT(!isNull()); - WebVector<CustomData> customData(static_cast<size_t>(m_private->customData().size())); - HashMap<String, String>::const_iterator begin = m_private->customData().begin(); - HashMap<String, String>::const_iterator end = m_private->customData().end(); - size_t i = 0; - for (HashMap<String, String>::const_iterator it = begin; it != end; ++it) { - CustomData data = {it->first, it->second}; - customData[i++] = data; + switch (item.storageType) { + case Item::StorageTypeString: + m_private->setData(item.stringType, item.stringData); + if (String(item.stringType) == mimeTypeTextURIList) + m_private->setUrlTitle(item.title); + else if (String(item.stringType) == mimeTypeTextHTML) + m_private->setHtmlBaseUrl(item.baseURL); + return; + case Item::StorageTypeFilename: + m_private->addFilename(item.filenameData); + return; + case Item::StorageTypeBinaryData: + // This should never happen when dragging in. + ASSERT_NOT_REACHED(); } - return customData; -} - -void WebDragData::setCustomData(const WebVector<WebDragData::CustomData>& customData) -{ - ensureMutable(); - HashMap<String, String>& customDataMap = m_private->customData(); - for (size_t i = 0; i < customData.size(); ++i) - customDataMap.set(customData[i].type, customData[i].data); } WebDragData::WebDragData(const WTF::PassRefPtr<WebCore::ChromiumDataObject>& data) diff --git a/Source/WebKit/chromium/src/WebFrameImpl.cpp b/Source/WebKit/chromium/src/WebFrameImpl.cpp index f8d2034fd..adf202371 100644 --- a/Source/WebKit/chromium/src/WebFrameImpl.cpp +++ b/Source/WebKit/chromium/src/WebFrameImpl.cpp @@ -123,8 +123,6 @@ #include "ReplaceSelectionCommand.h" #include "ResourceHandle.h" #include "ResourceRequest.h" -#include "SVGDocumentExtensions.h" -#include "SVGSMILElement.h" #include "SchemeRegistry.h" #include "ScriptController.h" #include "ScriptSourceCode.h" @@ -1303,7 +1301,7 @@ void WebFrameImpl::requestTextChecking(const WebElement& webElem) RefPtr<Range> rangeToCheck = rangeOfContents(const_cast<Element*>(webElem.constUnwrap<Element>())); - frame()->editor()->spellChecker()->requestCheckingFor(SpellCheckRequest::create(TextCheckingTypeSpelling | TextCheckingTypeGrammar, rangeToCheck, rangeToCheck)); + frame()->editor()->spellChecker()->requestCheckingFor(SpellCheckRequest::create(TextCheckingTypeSpelling | TextCheckingTypeGrammar, TextCheckingProcessBatch, rangeToCheck, rangeToCheck)); } bool WebFrameImpl::hasSelection() const @@ -1946,26 +1944,6 @@ bool WebFrameImpl::selectionStartHasSpellingMarkerFor(int from, int length) cons return m_frame->editor()->selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length); } -bool WebFrameImpl::pauseSVGAnimation(const WebString& animationId, double time, const WebString& elementId) -{ -#if !ENABLE(SVG) - return false; -#else - if (!m_frame) - return false; - - Document* document = m_frame->document(); - if (!document || !document->svgExtensions()) - return false; - - Node* coreNode = document->getElementById(animationId); - if (!coreNode || !SVGSMILElement::isSMILElement(coreNode)) - return false; - - return document->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreNode), time); -#endif -} - WebString WebFrameImpl::layerTreeAsText(bool showDebugInfo) const { if (!m_frame) diff --git a/Source/WebKit/chromium/src/WebFrameImpl.h b/Source/WebKit/chromium/src/WebFrameImpl.h index de38d0dca..700f6ea40 100644 --- a/Source/WebKit/chromium/src/WebFrameImpl.h +++ b/Source/WebKit/chromium/src/WebFrameImpl.h @@ -214,9 +214,6 @@ public: virtual WebRect selectionBoundsRect() const; virtual bool selectionStartHasSpellingMarkerFor(int from, int length) const; - virtual bool pauseSVGAnimation(const WebString& animationId, - double time, - const WebString& elementId); virtual WebString layerTreeAsText(bool showDebugInfo = false) const; static PassRefPtr<WebFrameImpl> create(WebFrameClient* client); diff --git a/Source/WebKit/chromium/src/WebIDBObjectStoreImpl.cpp b/Source/WebKit/chromium/src/WebIDBObjectStoreImpl.cpp index 1ec8af5bc..55a6add57 100755 --- a/Source/WebKit/chromium/src/WebIDBObjectStoreImpl.cpp +++ b/Source/WebKit/chromium/src/WebIDBObjectStoreImpl.cpp @@ -82,6 +82,11 @@ void WebIDBObjectStoreImpl::deleteFunction(const WebIDBKey& key, WebIDBCallbacks m_objectStore->deleteFunction(key, IDBCallbacksProxy::create(adoptPtr(callbacks)), transaction.getIDBTransactionBackendInterface(), ec); } +void WebIDBObjectStoreImpl::deleteFunction(const WebIDBKeyRange& keyRange, WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction, WebExceptionCode& ec) +{ + m_objectStore->deleteFunction(keyRange, IDBCallbacksProxy::create(adoptPtr(callbacks)), transaction.getIDBTransactionBackendInterface(), ec); +} + void WebIDBObjectStoreImpl::clear(WebIDBCallbacks* callbacks, const WebIDBTransaction& transaction, WebExceptionCode& ec) { m_objectStore->clear(IDBCallbacksProxy::create(adoptPtr(callbacks)), transaction.getIDBTransactionBackendInterface(), ec); diff --git a/Source/WebKit/chromium/src/WebIDBObjectStoreImpl.h b/Source/WebKit/chromium/src/WebIDBObjectStoreImpl.h index 6f580f01a..d2202fc7f 100644 --- a/Source/WebKit/chromium/src/WebIDBObjectStoreImpl.h +++ b/Source/WebKit/chromium/src/WebIDBObjectStoreImpl.h @@ -51,7 +51,8 @@ public: void get(const WebIDBKey& key, WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&); void put(const WebSerializedScriptValue&, const WebIDBKey&, PutMode, WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&); - void deleteFunction(const WebIDBKey& key, WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&); + void deleteFunction(const WebIDBKey&, WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&); + void deleteFunction(const WebIDBKeyRange&, WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&); void clear(WebIDBCallbacks*, const WebIDBTransaction&, WebExceptionCode&); // FIXME: Remove once callers are updated. diff --git a/Source/WebKit/chromium/src/WebInputElement.cpp b/Source/WebKit/chromium/src/WebInputElement.cpp index 5dadb0cf8..736165bbf 100644 --- a/Source/WebKit/chromium/src/WebInputElement.cpp +++ b/Source/WebKit/chromium/src/WebInputElement.cpp @@ -90,7 +90,7 @@ int WebInputElement::size() const void WebInputElement::setValue(const WebString& value, bool sendChangeEvent) { - unwrap<HTMLInputElement>()->setValue(value, sendChangeEvent); + unwrap<HTMLInputElement>()->setValue(value, sendChangeEvent ? DispatchChangeEvent : DispatchNoEvent); } WebString WebInputElement::value() const diff --git a/Source/WebKit/chromium/src/WebInputEventConversion.cpp b/Source/WebKit/chromium/src/WebInputEventConversion.cpp index 64ba31170..5cf0ccaec 100644 --- a/Source/WebKit/chromium/src/WebInputEventConversion.cpp +++ b/Source/WebKit/chromium/src/WebInputEventConversion.cpp @@ -389,6 +389,10 @@ WebMouseEventBuilder::WebMouseEventBuilder(const Widget* widget, const MouseEven windowY = p.y(); x = event.absoluteLocation().x() - widget->location().x(); y = event.absoluteLocation().y() - widget->location().y(); +#if ENABLE(POINTER_LOCK) + movementX = event.webkitMovementX(); + movementY = event.webkitMovementY(); +#endif clickCount = event.detail(); } diff --git a/Source/WebKit/chromium/src/WebKit.cpp b/Source/WebKit/chromium/src/WebKit.cpp index 2b2b2597c..77858c4e7 100644 --- a/Source/WebKit/chromium/src/WebKit.cpp +++ b/Source/WebKit/chromium/src/WebKit.cpp @@ -45,6 +45,10 @@ #include "WorkerContextExecutionProxy.h" #include "v8.h" +#if OS(DARWIN) +#include "WebSystemInterface.h" +#endif + #include <wtf/Assertions.h> #include <wtf/MainThread.h> #include <wtf/Threading.h> @@ -107,6 +111,10 @@ void initializeWithoutV8(WebKitPlatformSupport* webKitPlatformSupport) ASSERT(!s_webKitInitialized); s_webKitInitialized = true; +#if OS(DARWIN) + InitWebCoreSystemInterface(); +#endif + ASSERT(webKitPlatformSupport); ASSERT(!s_webKitPlatformSupport); s_webKitPlatformSupport = webKitPlatformSupport; diff --git a/Source/WebKit/chromium/src/WebLayerTreeView.cpp b/Source/WebKit/chromium/src/WebLayerTreeView.cpp index b288b563b..d2c0f0c12 100644 --- a/Source/WebKit/chromium/src/WebLayerTreeView.cpp +++ b/Source/WebKit/chromium/src/WebLayerTreeView.cpp @@ -43,11 +43,11 @@ WebLayerTreeView::Settings::operator CCSettings() const settings.showFPSCounter = showFPSCounter; settings.showPlatformLayerTree = showPlatformLayerTree; settings.refreshRate = refreshRate; + settings.perTilePainting = perTilePainting; settings.partialSwapEnabled = partialSwapEnabled; + settings.threadedAnimationEnabled = threadedAnimationEnabled; - // FIXME: showFPSCounter / showPlatformLayerTree aren't supported currently. - settings.showFPSCounter = false; - settings.showPlatformLayerTree = false; + // FIXME: showFPSCounter / showPlatformLayerTree / maxPartialTextureUpdates aren't supported currently. return settings; } @@ -118,4 +118,9 @@ WebLayerTreeView::operator PassRefPtr<CCLayerTreeHost>() const return m_private.get(); } +void WebLayerTreeView::setNeedsRedraw() +{ + m_private->setNeedsRedraw(); +} + } // namespace WebKit diff --git a/Source/WebKit/chromium/src/WebLayerTreeViewImpl.cpp b/Source/WebKit/chromium/src/WebLayerTreeViewImpl.cpp index 981477118..29d033215 100644 --- a/Source/WebKit/chromium/src/WebLayerTreeViewImpl.cpp +++ b/Source/WebKit/chromium/src/WebLayerTreeViewImpl.cpp @@ -86,21 +86,7 @@ PassRefPtr<GraphicsContext3D> WebLayerTreeViewImpl::createLayerTreeHostContext3D if (!webContext) return 0; - WebGraphicsContext3D::Attributes webAttributes = webContext->getContextAttributes(); - GraphicsContext3D::Attributes attributes; - attributes.alpha = webAttributes.alpha; - attributes.depth = webAttributes.depth; - attributes.stencil = webAttributes.stencil; - attributes.antialias = webAttributes.antialias; - attributes.premultipliedAlpha = webAttributes.premultipliedAlpha; - attributes.canRecoverFromContextLoss = webAttributes.canRecoverFromContextLoss; - attributes.noExtensions = webAttributes.noExtensions; - attributes.shareResources = webAttributes.shareResources; - attributes.preserveDrawingBuffer = false; - - GraphicsContext3D::RenderStyle style = GraphicsContext3D::RenderDirectlyToHostWindow; - GraphicsContext3DPrivate::ThreadUsage usage = CCProxy::hasImplThread() ? GraphicsContext3DPrivate::ForUseOnAnotherThread : GraphicsContext3DPrivate::ForUseOnThisThread; - return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(webContext.release(), attributes, 0, style, usage); + return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(webContext.release(), GraphicsContext3D::RenderDirectlyToHostWindow, false /* preserveDrawingBuffer */ ); } void WebLayerTreeViewImpl::didCommitAndDrawFrame() diff --git a/Source/WebKit/chromium/src/WebMediaPlayerClientImpl.cpp b/Source/WebKit/chromium/src/WebMediaPlayerClientImpl.cpp index 996e70710..ec74b6bea 100644 --- a/Source/WebKit/chromium/src/WebMediaPlayerClientImpl.cpp +++ b/Source/WebKit/chromium/src/WebMediaPlayerClientImpl.cpp @@ -28,6 +28,7 @@ #include "WebMediaElement.h" #include "WebMediaPlayer.h" #include "WebViewImpl.h" +#include "cc/CCProxy.h" #include "platform/WebCString.h" #include "platform/WebCanvas.h" #include "platform/WebKitPlatformSupport.h" @@ -105,6 +106,8 @@ WebMediaPlayerClientImpl::~WebMediaPlayerClientImpl() MutexLocker locker(m_compositingMutex); if (m_videoFrameProviderClient) m_videoFrameProviderClient->stopUsingProvider(); + if (m_webMediaPlayer) + m_webMediaPlayer->setStreamTextureClient(0); #endif } @@ -149,7 +152,7 @@ void WebMediaPlayerClientImpl::repaint() ASSERT(m_mediaPlayer); #if USE(ACCELERATED_COMPOSITING) if (m_videoLayer && supportsAcceleratedRendering()) - m_videoLayer->setNeedsDisplay(); + m_videoLayer->contentChanged(); #endif m_mediaPlayer->repaint(); } @@ -237,6 +240,7 @@ void WebMediaPlayerClientImpl::load(const String& url) m_url = url; if (m_preload == MediaPlayer::None) { + MutexLocker locker(m_compositingMutex); #if ENABLE(WEB_AUDIO) m_audioSourceProvider.wrap(0); // Clear weak reference to m_webMediaPlayer's WebAudioSourceProvider. #endif @@ -248,6 +252,7 @@ void WebMediaPlayerClientImpl::load(const String& url) void WebMediaPlayerClientImpl::loadInternal() { + MutexLocker locker(m_compositingMutex); #if ENABLE(WEB_AUDIO) m_audioSourceProvider.wrap(0); // Clear weak reference to m_webMediaPlayer's WebAudioSourceProvider. #endif @@ -597,6 +602,8 @@ void WebMediaPlayerClientImpl::setVideoFrameProviderClient(VideoFrameProvider::C { MutexLocker locker(m_compositingMutex); m_videoFrameProviderClient = client; + if (m_webMediaPlayer) + m_webMediaPlayer->setStreamTextureClient(client ? this : 0); } VideoFrameChromium* WebMediaPlayerClientImpl::getCurrentFrame() @@ -679,6 +686,20 @@ void WebMediaPlayerClientImpl::startDelayedLoad() loadInternal(); } +void WebMediaPlayerClientImpl::didReceiveFrame() +{ + // No lock since this gets called on the client's thread. + ASSERT(CCProxy::isImplThread()); + m_videoFrameProviderClient->didReceiveFrame(); +} + +void WebMediaPlayerClientImpl::didUpdateMatrix(const float* matrix) +{ + // No lock since this gets called on the client's thread. + ASSERT(CCProxy::isImplThread()); + m_videoFrameProviderClient->didUpdateMatrix(matrix); +} + WebMediaPlayerClientImpl::WebMediaPlayerClientImpl() : m_mediaPlayer(0) , m_delayingLoad(false) diff --git a/Source/WebKit/chromium/src/WebMediaPlayerClientImpl.h b/Source/WebKit/chromium/src/WebMediaPlayerClientImpl.h index e75e73ae1..d85e0d1fc 100644 --- a/Source/WebKit/chromium/src/WebMediaPlayerClientImpl.h +++ b/Source/WebKit/chromium/src/WebMediaPlayerClientImpl.h @@ -40,7 +40,9 @@ #include "VideoLayerChromium.h" #include "WebAudioSourceProviderClient.h" #include "WebMediaPlayerClient.h" +#include "WebStreamTextureClient.h" #include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> namespace WebCore { class AudioSourceProviderClient; } @@ -56,7 +58,8 @@ class WebMediaPlayerClientImpl : public WebCore::MediaPlayerPrivateInterface #if USE(ACCELERATED_COMPOSITING) , public WebCore::VideoFrameProvider #endif - , public WebMediaPlayerClient { + , public WebMediaPlayerClient + , public WebStreamTextureClient { public: static bool isEnabled(); @@ -150,6 +153,10 @@ public: virtual void sourceEndOfStream(WebCore::MediaPlayer::EndOfStreamStatus); #endif + // WebStreamTextureClient methods: + virtual void didReceiveFrame(); + virtual void didUpdateMatrix(const float*); + private: WebMediaPlayerClientImpl(); void startDelayedLoad(); diff --git a/Source/WebKit/chromium/src/WebPageSerializerImpl.cpp b/Source/WebKit/chromium/src/WebPageSerializerImpl.cpp index ca0583488..072a9909c 100644 --- a/Source/WebKit/chromium/src/WebPageSerializerImpl.cpp +++ b/Source/WebKit/chromium/src/WebPageSerializerImpl.cpp @@ -417,7 +417,6 @@ void WebPageSerializerImpl::buildContentForNode(Node* node, case Node::ATTRIBUTE_NODE: case Node::DOCUMENT_NODE: case Node::DOCUMENT_FRAGMENT_NODE: - case Node::SHADOW_ROOT_NODE: // Should not exist. ASSERT_NOT_REACHED(); break; diff --git a/Source/WebKit/chromium/src/WebPluginContainerImpl.cpp b/Source/WebKit/chromium/src/WebPluginContainerImpl.cpp index 129088ef4..10c3e2e4b 100644 --- a/Source/WebKit/chromium/src/WebPluginContainerImpl.cpp +++ b/Source/WebKit/chromium/src/WebPluginContainerImpl.cpp @@ -60,6 +60,7 @@ #include "FrameLoadRequest.h" #include "FrameView.h" #include "GraphicsContext.h" +#include "HitTestResult.h" #include "HostWindow.h" #include "HTMLFormElement.h" #include "HTMLNames.h" @@ -433,6 +434,26 @@ void WebPluginContainerImpl::zoomLevelChanged(double zoomLevel) WebViewImpl* view = WebViewImpl::fromPage(m_element->document()->frame()->page()); view->fullFramePluginZoomLevelChanged(zoomLevel); } + +bool WebPluginContainerImpl::isRectTopmost(const WebRect& rect) +{ + Page* page = m_element->document()->page(); + if (!page) + return false; + + // hitTestResultAtPoint() takes a padding rectangle. + // FIXME: We'll be off by 1 when the width or height is even. + IntRect windowRect = convertToContainingWindow(static_cast<IntRect>(rect)); + LayoutPoint center = windowRect.center(); + // Make the rect we're checking (the point surrounded by padding rects) contained inside the requested rect. (Note that -1/2 is 0.) + LayoutSize padding((windowRect.width() - 1) / 2, (windowRect.height() - 1) / 2); + HitTestResult result = + page->mainFrame()->eventHandler()->hitTestResultAtPoint(center, false, false, DontHitTestScrollbars, HitTestRequest::ReadOnly | HitTestRequest::Active, padding); + const HitTestResult::NodeSet& nodes = result.rectBasedTestResult(); + if (nodes.size() != 1) + return false; + return (nodes.first().get() == m_element); +} void WebPluginContainerImpl::didReceiveResponse(const ResourceResponse& response) { @@ -519,17 +540,6 @@ bool WebPluginContainerImpl::paintCustomOverhangArea(GraphicsContext* context, c return true; } -#if ENABLE(GESTURE_EVENTS) -bool WebPluginContainerImpl::handleGestureEvent(const WebCore::PlatformGestureEvent& gestureEvent) -{ - if (m_scrollbarGroup) { - m_scrollbarGroup->handleGestureEvent(gestureEvent); - return true; - } - return false; -} -#endif - // Private methods ------------------------------------------------------------- WebPluginContainerImpl::WebPluginContainerImpl(WebCore::HTMLPlugInElement* element, WebPlugin* webPlugin) diff --git a/Source/WebKit/chromium/src/WebPluginContainerImpl.h b/Source/WebKit/chromium/src/WebPluginContainerImpl.h index 8d6794d6f..898130084 100644 --- a/Source/WebKit/chromium/src/WebPluginContainerImpl.h +++ b/Source/WebKit/chromium/src/WebPluginContainerImpl.h @@ -104,6 +104,7 @@ public: virtual WebString executeScriptURL(const WebURL&, bool popupsAllowed); virtual void loadFrameRequest(const WebURLRequest&, const WebString& target, bool notifyNeeded, void* notifyData); virtual void zoomLevelChanged(double zoomLevel); + virtual bool isRectTopmost(const WebRect&); // This cannot be null. WebPlugin* plugin() { return m_webPlugin; } @@ -150,10 +151,6 @@ public: bool paintCustomOverhangArea(WebCore::GraphicsContext*, const WebCore::IntRect&, const WebCore::IntRect&, const WebCore::IntRect&); -#if ENABLE(GESTURE_EVENTS) - bool handleGestureEvent(const WebCore::PlatformGestureEvent&); -#endif - private: WebPluginContainerImpl(WebCore::HTMLPlugInElement* element, WebPlugin* webPlugin); ~WebPluginContainerImpl(); diff --git a/Source/WebKit/chromium/src/WebRuntimeFeatures.cpp b/Source/WebKit/chromium/src/WebRuntimeFeatures.cpp index 38963b521..f1960eb31 100644 --- a/Source/WebKit/chromium/src/WebRuntimeFeatures.cpp +++ b/Source/WebKit/chromium/src/WebRuntimeFeatures.cpp @@ -450,5 +450,23 @@ bool WebRuntimeFeatures::isShadowDOMEnabled() #endif } +void WebRuntimeFeatures::enableStyleScoped(bool enable) +{ +#if ENABLE(STYLE_SCOPED) + RuntimeEnabledFeatures::setStyleScopedEnabled(enable); +#else + UNUSED_PARAM(enable); +#endif +} + +bool WebRuntimeFeatures::isStyleScopedEnabled() +{ +#if ENABLE(STYLE_SCOPED) + return RuntimeEnabledFeatures::styleScopedEnabled(); +#else + return false; +#endif +} + } // namespace WebKit diff --git a/Source/WebKit/chromium/src/WebScopedUserGesture.cpp b/Source/WebKit/chromium/src/WebScopedUserGesture.cpp new file mode 100644 index 000000000..68426fcae --- /dev/null +++ b/Source/WebKit/chromium/src/WebScopedUserGesture.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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 + * OWNER 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 "WebScopedUserGesture.h" + +#include "UserGestureIndicator.h" + +namespace WebKit { + +void WebScopedUserGesture::initialize() +{ + m_indicator.reset(new WebCore::UserGestureIndicator(WebCore::DefinitelyProcessingUserGesture)); +} + +void WebScopedUserGesture::reset() +{ + m_indicator.reset(0); +} + +} // namespace WebKit diff --git a/Source/WebKit/chromium/src/WebSettingsImpl.cpp b/Source/WebKit/chromium/src/WebSettingsImpl.cpp index 11e9c337b..485a5b051 100644 --- a/Source/WebKit/chromium/src/WebSettingsImpl.cpp +++ b/Source/WebKit/chromium/src/WebSettingsImpl.cpp @@ -288,6 +288,11 @@ void WebSettingsImpl::setExperimentalWebGLEnabled(bool enabled) m_settings->setWebGLEnabled(enabled); } +void WebSettingsImpl::setExperimentalCSSRegionsEnabled(bool enabled) +{ + m_settings->setCSSRegionsEnabled(enabled); +} + void WebSettingsImpl::setOpenGLMultisamplingEnabled(bool enabled) { m_settings->setOpenGLMultisamplingEnabled(enabled); @@ -326,6 +331,7 @@ void WebSettingsImpl::setEditingBehavior(EditingBehavior behavior) void WebSettingsImpl::setAcceleratedCompositingEnabled(bool enabled) { m_settings->setAcceleratedCompositingEnabled(enabled); + m_settings->setScrollingCoordinatorEnabled(enabled); } void WebSettingsImpl::setForceCompositingMode(bool enabled) @@ -457,6 +463,16 @@ void WebSettingsImpl::setAllowRunningOfInsecureContent(bool enabled) m_settings->setAllowRunningOfInsecureContent(enabled); } +void WebSettingsImpl::setPasswordEchoEnabled(bool flag) +{ + m_settings->setPasswordEchoEnabled(flag); +} + +void WebSettingsImpl::setPasswordEchoDurationInSeconds(double durationInSeconds) +{ + m_settings->setPasswordEchoDurationInSeconds(durationInSeconds); +} + void WebSettingsImpl::setShouldPrintBackgrounds(bool enabled) { m_settings->setShouldPrintBackgrounds(enabled); @@ -527,4 +543,9 @@ void WebSettingsImpl::setPartialSwapEnabled(bool enabled) m_settings->setPartialSwapEnabled(enabled); } +void WebSettingsImpl::setThreadedAnimationEnabled(bool enabled) +{ + m_settings->setThreadedAnimationEnabled(enabled); +} + } // namespace WebKit diff --git a/Source/WebKit/chromium/src/WebSettingsImpl.h b/Source/WebKit/chromium/src/WebSettingsImpl.h index 45e62db6f..51d9323a4 100644 --- a/Source/WebKit/chromium/src/WebSettingsImpl.h +++ b/Source/WebKit/chromium/src/WebSettingsImpl.h @@ -88,6 +88,7 @@ public: virtual void setOfflineWebApplicationCacheEnabled(bool); virtual void setWebAudioEnabled(bool); virtual void setExperimentalWebGLEnabled(bool); + virtual void setExperimentalCSSRegionsEnabled(bool); virtual void setOpenGLMultisamplingEnabled(bool); virtual void setPrivilegedWebGLExtensionsEnabled(bool); virtual void setWebGLErrorsToConsoleEnabled(bool); @@ -124,6 +125,8 @@ public: virtual void setFullScreenEnabled(bool); virtual void setAllowDisplayOfInsecureContent(bool); virtual void setAllowRunningOfInsecureContent(bool); + virtual void setPasswordEchoEnabled(bool); + virtual void setPasswordEchoDurationInSeconds(double); virtual void setShouldPrintBackgrounds(bool); virtual void setEnableScrollAnimator(bool); virtual void setHixie76WebSocketProtocolEnabled(bool); @@ -134,6 +137,7 @@ public: virtual void setAcceleratedPaintingEnabled(bool); virtual void setPerTilePaintingEnabled(bool); virtual void setPartialSwapEnabled(bool); + virtual void setThreadedAnimationEnabled(bool); private: WebCore::Settings* m_settings; diff --git a/Source/WebKit/chromium/src/WebSharedWorkerImpl.cpp b/Source/WebKit/chromium/src/WebSharedWorkerImpl.cpp index 7a4bddb22..3fa19d25d 100644 --- a/Source/WebKit/chromium/src/WebSharedWorkerImpl.cpp +++ b/Source/WebKit/chromium/src/WebSharedWorkerImpl.cpp @@ -443,6 +443,7 @@ static void dispatchOnInspectorBackendTask(ScriptExecutionContext* context, cons void WebSharedWorkerImpl::dispatchDevToolsMessage(const WebString& message) { workerThread()->runLoop().postTaskForMode(createCallbackTask(dispatchOnInspectorBackendTask, String(message)), WorkerDebuggerAgent::debuggerTaskMode); + WorkerDebuggerAgent::interruptAndDispatchInspectorCommands(workerThread()); } WebSharedWorker* WebSharedWorker::create(WebSharedWorkerClient* client) diff --git a/Source/WebKit/chromium/src/WebURLResponse.cpp b/Source/WebKit/chromium/src/WebURLResponse.cpp index 2eacda580..ec212e517 100644 --- a/Source/WebKit/chromium/src/WebURLResponse.cpp +++ b/Source/WebKit/chromium/src/WebURLResponse.cpp @@ -47,6 +47,27 @@ using namespace WebCore; namespace WebKit { +namespace { + +class ExtraDataContainer : public ResourceResponse::ExtraData { +public: + static PassRefPtr<ExtraDataContainer> create(WebURLResponse::ExtraData* extraData) { return adoptRef(new ExtraDataContainer(extraData)); } + + virtual ~ExtraDataContainer() { } + + WebURLResponse::ExtraData* extraData() const { return m_extraData.get(); } + +private: + explicit ExtraDataContainer(WebURLResponse::ExtraData* extraData) + : m_extraData(adoptPtr(extraData)) + { + } + + OwnPtr<WebURLResponse::ExtraData> m_extraData; +}; + +} // namespace + // The standard implementation of WebURLResponsePrivate, which maintains // ownership of a ResourceResponse instance. class WebURLResponsePrivateImpl : public WebURLResponsePrivate { @@ -399,6 +420,19 @@ void WebURLResponse::setRemotePort(unsigned short remotePort) m_private->m_resourceResponse->setRemotePort(remotePort); } +WebURLResponse::ExtraData* WebURLResponse::extraData() const +{ + RefPtr<ResourceResponse::ExtraData> data = m_private->m_resourceResponse->extraData(); + if (!data) + return 0; + return static_cast<ExtraDataContainer*>(data.get())->extraData(); +} + +void WebURLResponse::setExtraData(WebURLResponse::ExtraData* extraData) +{ + m_private->m_resourceResponse->setExtraData(ExtraDataContainer::create(extraData)); +} + void WebURLResponse::assign(WebURLResponsePrivate* p) { // Subclasses may call this directly so a self-assignment check is needed diff --git a/Source/WebKit/chromium/src/WebViewImpl.cpp b/Source/WebKit/chromium/src/WebViewImpl.cpp index a05e98920..55a2052a4 100644 --- a/Source/WebKit/chromium/src/WebViewImpl.cpp +++ b/Source/WebKit/chromium/src/WebViewImpl.cpp @@ -99,7 +99,6 @@ #include "RenderWidget.h" #include "ResourceHandle.h" #include "SchemeRegistry.h" -#include "ScrollAnimator.h" #include "SecurityOrigin.h" #include "SecurityPolicy.h" #include "Settings.h" @@ -171,7 +170,7 @@ using namespace std; namespace { -GraphicsContext3D::Attributes getCompositorContextAttributes() +WebKit::WebGraphicsContext3D::Attributes getCompositorContextAttributes(bool threaded) { // Explicitly disable antialiasing for the compositor. As of the time of // this writing, the only platform that supported antialiasing for the @@ -183,12 +182,21 @@ GraphicsContext3D::Attributes getCompositorContextAttributes() // be optimized to resolve directly into the IOSurface shared between the // GPU and browser processes. For these reasons and to avoid platform // disparities we explicitly disable antialiasing. - GraphicsContext3D::Attributes attributes; + WebKit::WebGraphicsContext3D::Attributes attributes; attributes.antialias = false; attributes.shareResources = true; + attributes.forUseOnAnotherThread = threaded; return attributes; } +// The following constants control parameters for automated scaling of webpages +// (such as due to a double tap gesture or find in page etc.). These are +// experimentally determined. +static const int touchPointPadding = 32; +static const float minScaleDifference = 0.01; +static const float doubleTapZoomContentDefaultMargin = 5; +static const float doubleTapZoomContentMinimumMargin = 2; + } // anonymous namespace namespace WebKit { @@ -390,21 +398,21 @@ WebViewImpl::WebViewImpl(WebViewClient* client) pageClients.editorClient = &m_editorClientImpl; pageClients.dragClient = &m_dragClientImpl; pageClients.inspectorClient = &m_inspectorClientImpl; -#if ENABLE(INPUT_SPEECH) - pageClients.speechInputClient = m_speechInputClient.get(); -#endif - pageClients.deviceOrientationClient = m_deviceOrientationClientProxy.get(); pageClients.geolocationClient = m_geolocationClientProxy.get(); -#if ENABLE(NOTIFICATIONS) - pageClients.notificationClient = notificationPresenterImpl(); -#endif pageClients.backForwardClient = BackForwardListChromium::create(this); -#if ENABLE(MEDIA_STREAM) - pageClients.userMediaClient = &m_userMediaClientImpl; -#endif m_page = adoptPtr(new Page(pageClients)); +#if ENABLE(MEDIA_STREAM) + provideUserMediaTo(m_page.get(), &m_userMediaClientImpl); +#endif +#if ENABLE(INPUT_SPEECH) + provideSpeechInputTo(m_page.get(), m_speechInputClient.get()); +#endif +#if ENABLE(NOTIFICATIONS) + provideNotification(m_page.get(), notificationPresenterImpl()); +#endif + provideDeviceOrientationTo(m_page.get(), m_deviceOrientationClientProxy.get()); m_geolocationClientProxy->setController(m_page->geolocationController()); m_page->setGroupName(pageGroupName); @@ -614,14 +622,13 @@ bool WebViewImpl::mouseWheel(const WebMouseWheelEvent& event) bool WebViewImpl::gestureEvent(const WebGestureEvent& event) { PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event); - bool handled = mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent); - - Frame* frame = mainFrameImpl()->frame(); - WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame); - if (pluginContainer) - handled |= pluginContainer->handleGestureEvent(platformEvent); + return mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent); +} - return handled; +void WebViewImpl::startPageScaleAnimation(const IntPoint& scroll, bool useAnchor, float newScale, double durationSec) +{ + if (m_layerTreeHost) + m_layerTreeHost->startPageScaleAnimation(IntSize(scroll.x(), scroll.y()), useAnchor, newScale, durationSec); } #endif @@ -797,15 +804,159 @@ bool WebViewImpl::touchEvent(const WebTouchEvent& event) } #endif +#if ENABLE(GESTURE_EVENTS) +WebRect WebViewImpl::computeBlockBounds(const WebRect& rect, AutoZoomType zoomType) +{ + if (!mainFrameImpl()) + return WebRect(); + + // Use the rect-based hit test to find the node. + IntPoint point = mainFrameImpl()->frameView()->windowToContents(IntPoint(rect.x, rect.y)); + HitTestResult result = mainFrameImpl()->frame()->eventHandler()->hitTestResultAtPoint(point, + false, zoomType == FindInPage, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, + IntSize(rect.width, rect.height)); + + Node* node = result.innerNonSharedNode(); + if (!node) + return WebRect(); + + // Find the block type node based on the hit node. + while (node && (!node->renderer() || node->renderer()->isInline())) + node = node->parentNode(); + + // Return the bounding box in the window coordinate system. + if (node) { + IntRect rect = node->Node::getRect(); + Frame* frame = node->document()->frame(); + return frame->view()->contentsToWindow(rect); + } + return WebRect(); +} + +WebRect WebViewImpl::widenRectWithinPageBounds(const WebRect& source, int targetMargin, int minimumMargin) +{ + WebSize maxSize; + if (mainFrame()) + maxSize = mainFrame()->contentsSize(); + IntSize scrollOffset; + if (mainFrame()) + scrollOffset = mainFrame()->scrollOffset(); + int leftMargin = targetMargin; + int rightMargin = targetMargin; + + const int absoluteSourceX = source.x + scrollOffset.width(); + if (leftMargin > absoluteSourceX) { + leftMargin = absoluteSourceX; + rightMargin = max(leftMargin, minimumMargin); + } + + const int maximumRightMargin = maxSize.width - (source.width + absoluteSourceX); + if (rightMargin > maximumRightMargin) { + rightMargin = maximumRightMargin; + leftMargin = min(leftMargin, max(rightMargin, minimumMargin)); + } + + const int newWidth = source.width + leftMargin + rightMargin; + const int newX = source.x - leftMargin; + + ASSERT(newWidth >= 0); + ASSERT(scrollOffset.width() + newX + newWidth <= maxSize.width); + + return WebRect(newX, source.y, newWidth, source.height); +} + +void WebViewImpl::computeScaleAndScrollForHitRect(const WebRect& hitRect, AutoZoomType zoomType, float& scale, WebPoint& scroll) +{ + scale = pageScaleFactor(); + scroll.x = scroll.y = 0; + WebRect targetRect = hitRect; + if (targetRect.isEmpty()) + targetRect.width = targetRect.height = touchPointPadding; + + WebRect rect = computeBlockBounds(targetRect, zoomType); + + const float overviewScale = m_minimumPageScaleFactor; + bool scaleUnchanged = true; + if (!rect.isEmpty()) { + // Pages should be as legible as on desktop when at dpi scale, so no + // need to zoom in further when automatically determining zoom level + // (after double tap, find in page, etc), though the user should still + // be allowed to manually pinch zoom in further if they desire. + const float maxScale = deviceScaleFactor(); + + const float defaultMargin = doubleTapZoomContentDefaultMargin * deviceScaleFactor(); + const float minimumMargin = doubleTapZoomContentMinimumMargin * deviceScaleFactor(); + // We want the margins to have the same physical size, which means we + // need to express them in post-scale size. To do that we'd need to know + // the scale we're scaling to, but that depends on the margins. Instead + // we express them as a fraction of the target rectangle: this will be + // correct if we end up fully zooming to it, and won't matter if we + // don't. + rect = widenRectWithinPageBounds(rect, + static_cast<int>(defaultMargin * rect.width / m_size.width), + static_cast<int>(minimumMargin * rect.width / m_size.width)); + + // Fit block to screen, respecting limits. + scale *= static_cast<float>(m_size.width) / rect.width; + scale = min(scale, maxScale); + scale = clampPageScaleFactorToLimits(scale); + + scaleUnchanged = fabs(pageScaleFactor() - scale) < minScaleDifference; + } + + if (zoomType == DoubleTap) { + if (rect.isEmpty() || scaleUnchanged) { + // Zoom out to overview mode. + if (overviewScale) + scale = overviewScale; + return; + } + } else if (rect.isEmpty()) { + // Keep current scale (no need to scroll as x,y will normally already + // be visible). FIXME: Revisit this if it isn't always true. + return; + } + + // FIXME: If this is being called for auto zoom during find in page, + // then if the user manually zooms in it'd be nice to preserve the relative + // increase in zoom they caused (if they zoom out then it's ok to zoom + // them back in again). This isn't compatible with our current double-tap + // zoom strategy (fitting the containing block to the screen) though. + + float screenHeight = m_size.height / scale * pageScaleFactor(); + float screenWidth = m_size.width / scale * pageScaleFactor(); + + // Scroll to vertically align the block. + if (rect.height < screenHeight) { + // Vertically center short blocks. + rect.y -= 0.5 * (screenHeight - rect.height); + } else { + // Ensure position we're zooming to (+ padding) isn't off the bottom of + // the screen. + rect.y = max<float>(rect.y, hitRect.y + touchPointPadding - screenHeight); + } // Otherwise top align the block. + + // Do the same thing for horizontal alignment. + if (rect.width < screenWidth) + rect.x -= 0.5 * (screenWidth - rect.width); + else + rect.x = max<float>(rect.x, hitRect.x + touchPointPadding - screenWidth); + + scroll.x = rect.x; + scroll.y = rect.y; +} +#endif + void WebViewImpl::numberOfWheelEventHandlersChanged(unsigned numberOfWheelHandlers) { - m_haveWheelEventHandlers = numberOfWheelHandlers > 0; if (m_client) m_client->numberOfWheelEventHandlersChanged(numberOfWheelHandlers); -#if USE(ACCELERATED_COMPOSITING) - if (m_layerTreeHost) - m_layerTreeHost->setHaveWheelEventHandlers(m_haveWheelEventHandlers); -#endif +} + +void WebViewImpl::numberOfTouchEventHandlersChanged(unsigned numberOfTouchHandlers) +{ + if (m_client) + m_client->numberOfTouchEventHandlersChanged(numberOfTouchHandlers); } #if !OS(DARWIN) @@ -1257,6 +1408,14 @@ void WebViewImpl::composite(bool) #endif } +void WebViewImpl::setNeedsRedraw() +{ +#if USE(ACCELERATED_COMPOSITING) + if (m_layerTreeHost && isAcceleratedCompositingActive()) + m_layerTreeHost->setNeedsRedraw(); +#endif +} + void WebViewImpl::loseCompositorContext(int numTimes) { #if USE(ACCELERATED_COMPOSITING) @@ -2140,12 +2299,12 @@ bool WebViewImpl::computePageScaleFactorLimits() m_maximumPageScaleFactor = max(m_minimumPageScaleFactor, m_maximumPageScaleFactor); } ASSERT(m_minimumPageScaleFactor <= m_maximumPageScaleFactor); + + float clampedScale = clampPageScaleFactorToLimits(pageScaleFactor()); #if USE(ACCELERATED_COMPOSITING) if (m_layerTreeHost) - m_layerTreeHost->setPageScaleFactorLimits(m_minimumPageScaleFactor, m_maximumPageScaleFactor); + m_layerTreeHost->setPageScaleFactorAndLimits(clampedScale, m_minimumPageScaleFactor, m_maximumPageScaleFactor); #endif - - float clampedScale = clampPageScaleFactorToLimits(pageScaleFactor()); if (clampedScale != pageScaleFactor()) { setPageScaleFactorPreservingScrollOffset(clampedScale); return true; @@ -3005,6 +3164,7 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active) ccSettings.perTilePainting = page()->settings()->perTileDrawingEnabled(); ccSettings.partialSwapEnabled = page()->settings()->partialSwapEnabled(); + ccSettings.threadedAnimationEnabled = page()->settings()->threadedAnimationEnabled(); m_nonCompositedContentHost = NonCompositedContentHost::create(WebViewImplContentPainter::create(this)); m_nonCompositedContentHost->setShowDebugBorders(page()->settings()->showDebugBorders()); @@ -3014,8 +3174,7 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active) m_layerTreeHost = CCLayerTreeHost::create(this, ccSettings); if (m_layerTreeHost) { - m_layerTreeHost->setHaveWheelEventHandlers(m_haveWheelEventHandlers); - m_layerTreeHost->setPageScaleFactorLimits(m_minimumPageScaleFactor, m_maximumPageScaleFactor); + m_layerTreeHost->setPageScaleFactorAndLimits(pageScaleFactor(), m_minimumPageScaleFactor, m_maximumPageScaleFactor); updateLayerTreeViewport(); m_client->didActivateCompositor(m_layerTreeHost->compositorIdentifier()); m_isAcceleratedCompositingActive = true; @@ -3036,15 +3195,25 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active) #endif +PassRefPtr<GraphicsContext3D> WebViewImpl::createCompositorGraphicsContext3D() +{ + WebKit::WebGraphicsContext3D::Attributes attributes = getCompositorContextAttributes(CCProxy::hasImplThread()); + OwnPtr<WebGraphicsContext3D> webContext = adoptPtr(client()->createGraphicsContext3D(attributes, true /* renderDirectlyToHostWindow */)); + if (!webContext) + return 0; + + return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(webContext.release(), GraphicsContext3D::RenderDirectlyToHostWindow); +} + PassRefPtr<GraphicsContext3D> WebViewImpl::createLayerTreeHostContext3D() { - RefPtr<GraphicsContext3D> context = m_temporaryOnscreenGraphicsContext3D.release(); - if (!context) { - if (CCProxy::hasImplThread()) - context = GraphicsContext3DPrivate::createGraphicsContextForAnotherThread(getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow); - else - context = GraphicsContext3D::create(getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow); - } + RefPtr<GraphicsContext3D> context; + + // If we've already created an onscreen context for this view, return that. + if (m_temporaryOnscreenGraphicsContext3D) + context = m_temporaryOnscreenGraphicsContext3D.release(); + else // Otherwise make a new one. + context = createCompositorGraphicsContext3D(); return context; } @@ -3125,7 +3294,7 @@ void WebViewImpl::updateLayerTreeViewport() } m_nonCompositedContentHost->setViewport(visibleRect.size(), view->contentsSize(), scroll, pageScaleFactor(), layerAdjustX); m_layerTreeHost->setViewportSize(visibleRect.size()); - m_layerTreeHost->setPageScale(pageScaleFactor()); + m_layerTreeHost->setPageScaleFactorAndLimits(pageScaleFactor(), m_minimumPageScaleFactor, m_maximumPageScaleFactor); } WebGraphicsContext3D* WebViewImpl::graphicsContext3D() @@ -3137,17 +3306,16 @@ WebGraphicsContext3D* WebViewImpl::graphicsContext3D() if (webContext && !webContext->isContextLost()) return webContext; } - if (m_temporaryOnscreenGraphicsContext3D) { - WebGraphicsContext3D* webContext = GraphicsContext3DPrivate::extractWebGraphicsContext3D(m_temporaryOnscreenGraphicsContext3D.get()); - if (webContext && !webContext->isContextLost()) - return webContext; - } - if (CCProxy::hasImplThread()) - m_temporaryOnscreenGraphicsContext3D = GraphicsContext3DPrivate::createGraphicsContextForAnotherThread(getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow); - else - m_temporaryOnscreenGraphicsContext3D = GraphicsContext3D::create(getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow); - - return GraphicsContext3DPrivate::extractWebGraphicsContext3D(m_temporaryOnscreenGraphicsContext3D.get()); + // If we get here it means that some system needs access to the context the compositor will use but the compositor itself + // hasn't requested a context or it was unable to successfully instantiate a context. + // We need to return the context that the compositor will later use so we allocate a new context (if needed) and stash it + // until the compositor requests and takes ownership of the context via createLayerTreeHost3D(). + if (!m_temporaryOnscreenGraphicsContext3D) + m_temporaryOnscreenGraphicsContext3D = createCompositorGraphicsContext3D(); + + WebGraphicsContext3D* webContext = GraphicsContext3DPrivate::extractWebGraphicsContext3D(m_temporaryOnscreenGraphicsContext3D.get()); + if (webContext && !webContext->isContextLost()) + return webContext; } #endif return 0; diff --git a/Source/WebKit/chromium/src/WebViewImpl.h b/Source/WebKit/chromium/src/WebViewImpl.h index 800d18254..bc7a53d04 100644 --- a/Source/WebKit/chromium/src/WebViewImpl.h +++ b/Source/WebKit/chromium/src/WebViewImpl.h @@ -45,6 +45,7 @@ #include "GraphicsContext3D.h" #include "GraphicsLayer.h" #include "InspectorClientImpl.h" +#include "IntPoint.h" #include "IntRect.h" #include "NotificationPresenterImpl.h" #include "PageOverlayList.h" @@ -95,6 +96,11 @@ class WebTouchEvent; class WebViewImpl : public WebView, public WebCore::CCLayerTreeHostClient, public RefCounted<WebViewImpl> { public: + enum AutoZoomType { + DoubleTap, + FindInPage, + }; + // WebWidget methods: virtual void close(); virtual WebSize size() { return m_size; } @@ -110,6 +116,7 @@ public: virtual void paint(WebCanvas*, const WebRect&); virtual void themeChanged(); virtual void composite(bool finish); + virtual void setNeedsRedraw(); virtual bool handleInputEvent(const WebInputEvent&); virtual void mouseCaptureLost(); virtual void setFocus(bool enable); @@ -314,11 +321,13 @@ public: void mouseDoubleClick(const WebMouseEvent&); bool mouseWheel(const WebMouseWheelEvent&); bool gestureEvent(const WebGestureEvent&); + void startPageScaleAnimation(const WebCore::IntPoint& targetPosition, bool useAnchor, float newScale, double durationSec); bool keyEvent(const WebKeyboardEvent&); bool charEvent(const WebKeyboardEvent&); bool touchEvent(const WebTouchEvent&); void numberOfWheelEventHandlersChanged(unsigned); + void numberOfTouchEventHandlersChanged(unsigned); // Handles context menu events orignated via the the keyboard. These // include the VK_APPS virtual key and the Shift+F10 combine. Code is @@ -437,9 +446,12 @@ public: // Returns the onscreen 3D context used by the compositor. This is // used by the renderer's code to set up resource sharing between // the compositor's context and subordinate contexts for APIs like - // WebGL. Returns 0 if compositing support is not compiled in. + // WebGL. Returns 0 if compositing support is not compiled in or + // we could not successfully instantiate a context. virtual WebGraphicsContext3D* graphicsContext3D(); + PassRefPtr<WebCore::GraphicsContext3D> createCompositorGraphicsContext3D(); + virtual void setVisibilityState(WebPageVisibilityState, bool); WebCore::PopupContainer* selectPopup() const { return m_selectPopup.get(); } @@ -455,6 +467,10 @@ public: // a plugin can update its own zoom, say because of its own UI. void fullFramePluginZoomLevelChanged(double zoomLevel); +#if ENABLE(GESTURE_EVENTS) + void computeScaleAndScrollForHitRect(const WebRect& hitRect, AutoZoomType, float& scale, WebPoint& scroll); +#endif + void loseCompositorContext(int numTimes); void enterFullScreenForElement(WebCore::Element*); @@ -525,6 +541,15 @@ private: void updateLayerTreeViewport(); #endif +#if ENABLE(GESTURE_EVENTS) + // Returns the bounding box of the block type node touched by the WebRect. + WebRect computeBlockBounds(const WebRect&, AutoZoomType); + + // Helper function: Widens the width of |source| by the specified margins + // while keeping it smaller than page width. + WebRect widenRectWithinPageBounds(const WebRect& source, int targetMargin, int minimumMargin); +#endif + #if ENABLE(POINTER_LOCK) void pointerLockMouseEvent(const WebInputEvent&); #endif @@ -670,7 +695,6 @@ private: // If true, the graphics context is being restored. bool m_recreatingGraphicsContext; #endif - bool m_haveWheelEventHandlers; static const WebInputEvent* m_currentInputEvent; #if ENABLE(INPUT_SPEECH) diff --git a/Source/WebKit/chromium/src/WebWorkerClientImpl.cpp b/Source/WebKit/chromium/src/WebWorkerClientImpl.cpp index 796ab166d..1db2d1dd9 100644 --- a/Source/WebKit/chromium/src/WebWorkerClientImpl.cpp +++ b/Source/WebKit/chromium/src/WebWorkerClientImpl.cpp @@ -39,6 +39,7 @@ #include "ErrorEvent.h" #include "Frame.h" #include "FrameLoaderClient.h" +#include "InspectorInstrumentation.h" #include "MessageEvent.h" #include "MessagePort.h" #include "MessagePortChannel.h" @@ -90,6 +91,7 @@ void WebWorkerClientImpl::startWorkerContext(const KURL& scriptURL, const String m_scriptExecutionContext->contentSecurityPolicy()->headerType()); m_proxy->workerThreadCreated(thread); thread->start(); + InspectorInstrumentation::didStartWorkerContext(m_scriptExecutionContext.get(), m_proxy, scriptURL); } void WebWorkerClientImpl::terminateWorkerContext() diff --git a/Source/WebKit/chromium/src/js/Tests.js b/Source/WebKit/chromium/src/js/Tests.js index a41eefdd0..16a1ba257 100644 --- a/Source/WebKit/chromium/src/js/Tests.js +++ b/Source/WebKit/chromium/src/js/Tests.js @@ -308,7 +308,6 @@ TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch = function() this.showPanel("scripts"); - function switchToElementsTab() { test.showPanel("elements"); setTimeout(switchToScriptsTab, 0); @@ -320,19 +319,17 @@ TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch = function() } function checkScriptsPanel() { - test.assertTrue(!!WebInspector.panels.scripts.visibleView, "No visible script view."); test.assertTrue(test._scriptsAreParsed(["debugger_test_page.html"]), "Some scripts are missing."); checkNoDuplicates(); test.releaseControl(); } function checkNoDuplicates() { - var scriptSelect = document.getElementById("scripts-files"); - var options = scriptSelect.options; - for (var i = 0; i < options.length; i++) { - var scriptName = options[i].text; - for (var j = i + 1; j < options.length; j++) - test.assertTrue(scriptName !== options[j].text, "Found script duplicates: " + test.optionsToString_(options)); + var uiSourceCodes = test.nonAnonymousUISourceCodes_(); + for (var i = 0; i < uiSourceCodes.length; i++) { + var scriptName = uiSourceCodes[i].fileName; + for (var j = i + 1; j < uiSourceCodes.length; j++) + test.assertTrue(scriptName !== uiSourceCodes[j].fileName, "Found script duplicates: " + test.uiSourceCodesToString_(uiSourceCodes)); } } @@ -584,70 +581,32 @@ TestSuite.prototype.waitForTestResultsInConsole = function() /** - * Serializes options collection to string. - * @param {HTMLOptionsCollection} options + * Serializes array of uiSourceCodes to string. + * @param {Array.<WebInspectorUISourceCode>} uiSourceCodes * @return {string} */ -TestSuite.prototype.optionsToString_ = function(options) +TestSuite.prototype.uiSourceCodesToString_ = function(uiSourceCodes) { var names = []; - for (var i = 0; i < options.length; i++) - names.push('"' + options[i].text + '"'); + for (var i = 0; i < uiSourceCodes.length; i++) + names.push('"' + uiSourceCodes[i].fileName + '"'); return names.join(","); }; /** - * Ensures that main HTML resource is selected in Scripts panel and that its - * source frame is setup. Invokes the callback when the condition is satisfied. - * @param {HTMLOptionsCollection} options - * @param {function(WebInspector.SourceView,string)} callback + * Returns all loaded non anonymous uiSourceCodes. + * @return {Array.<WebInspectorUISourceCode>} */ -TestSuite.prototype.showMainPageScriptSource_ = function(scriptName, callback) +TestSuite.prototype.nonAnonymousUISourceCodes_ = function() { - var test = this; - - var scriptSelect = document.getElementById("scripts-files"); - var options = scriptSelect.options; - - test.assertTrue(options.length, "Scripts list is empty"); - - // Select page's script if it's not current option. - var scriptResource; - if (options[scriptSelect.selectedIndex].text === scriptName) - scriptResource = options[scriptSelect.selectedIndex].representedObject; - else { - var pageScriptIndex = -1; - for (var i = 0; i < options.length; i++) { - if (options[i].text === scriptName) { - pageScriptIndex = i; - break; - } - } - test.assertTrue(-1 !== pageScriptIndex, "Script with url " + scriptName + " not found among " + test.optionsToString_(options)); - scriptResource = options[pageScriptIndex].representedObject; - - // Current panel is "Scripts". - WebInspector.inspectorView.currentPanel()._showScriptOrResource(scriptResource); - test.assertEquals(pageScriptIndex, scriptSelect.selectedIndex, "Unexpected selected option index."); + function filterOutAnonymous(uiSourceCode) + { + return !!uiSourceCode.url; } - test.assertTrue(scriptResource instanceof WebInspector.Resource, - "Unexpected resource class."); - test.assertTrue(!!scriptResource.url, "Resource URL is null."); - test.assertTrue(scriptResource.url.search(scriptName + "$") !== -1, "Main HTML resource should be selected."); - - var scriptsPanel = WebInspector.panels.scripts; - - var view = scriptsPanel.visibleView; - test.assertTrue(view instanceof WebInspector.SourceView); - - if (!view.sourceFrame._loaded) { - test.addSniffer(view, "_sourceFrameSetupFinished", function(event) { - callback(view, scriptResource.url); - }); - } else - callback(view, scriptResource.url); + var uiSourceCodes = WebInspector.panels.scripts._presentationModel.uiSourceCodes(); + return uiSourceCodes.filter(filterOutAnonymous); }; @@ -680,14 +639,12 @@ TestSuite.prototype.evaluateInConsole_ = function(code, callback) */ TestSuite.prototype._scriptsAreParsed = function(expected) { - var scriptSelect = document.getElementById("scripts-files"); - var options = scriptSelect.options; - + var uiSourceCodes = this.nonAnonymousUISourceCodes_(); // Check that at least all the expected scripts are present. var missing = expected.slice(0); - for (var i = 0 ; i < options.length; i++) { - for (var j = 0; j < missing.length; j++) { - if (options[i].text.search(missing[j]) !== -1) { + for (var i = 0; i < uiSourceCodes.length; ++i) { + for (var j = 0; j < missing.length; ++j) { + if (uiSourceCodes[i].fileName.search(missing[j]) !== -1) { missing.splice(j, 1); break; } @@ -744,7 +701,7 @@ TestSuite.prototype._waitUntilScriptsAreParsed = function(expectedScripts, callb if (test._scriptsAreParsed(expectedScripts)) callback(); else - test.addSniffer(WebInspector.panels.scripts, "_uiSourceCodeAdded", waitForAllScripts); + test.addSniffer(WebInspector.panels.scripts, "_addUISourceCode", waitForAllScripts); } waitForAllScripts(); diff --git a/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp b/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp index 3e93d95de..e14ef9bc0 100644 --- a/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp +++ b/Source/WebKit/chromium/tests/CCActiveAnimationTest.cpp @@ -25,24 +25,20 @@ #include "config.h" #include "cc/CCActiveAnimation.h" - -#include "cc/CCAnimationCurve.h" +#include "CCAnimationTestCommon.h" #include <gmock/gmock.h> #include <gtest/gtest.h> #include <wtf/Vector.h> -namespace WebCore { +using namespace WebKitTests; +using namespace WebCore; -class FakeFloatAnimation : public CCFloatAnimationCurve { -public: - virtual double duration() const { return 1; } - virtual float getValue(double now) const { return 0; } -}; +namespace { PassOwnPtr<CCActiveAnimation> createActiveAnimation(int iterations) { - OwnPtr<CCActiveAnimation> toReturn(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimation), 1, CCActiveAnimation::Opacity)); + OwnPtr<CCActiveAnimation> toReturn(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimationCurve), 0, 1, CCActiveAnimation::Opacity)); toReturn->setIterations(iterations); return toReturn.release(); } @@ -164,4 +160,4 @@ TEST(CCActiveAnimationTest, IsFinished) EXPECT_TRUE(anim->isFinished()); } -} // namespace WebCore +} // namespace diff --git a/Source/WebKit/chromium/tests/CCAnimationTestCommon.cpp b/Source/WebKit/chromium/tests/CCAnimationTestCommon.cpp new file mode 100644 index 000000000..c9240e31f --- /dev/null +++ b/Source/WebKit/chromium/tests/CCAnimationTestCommon.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "CCAnimationTestCommon.h" + +#include "GraphicsLayer.h" +#include "LayerChromium.h" +#include "cc/CCLayerAnimationController.h" + +using namespace WebCore; + +namespace { + +template <class Target> +void addOpacityTransition(Target& target, double duration, float startOpacity, float endOpacity) +{ + WebCore::KeyframeValueList values(AnimatedPropertyOpacity); + if (duration > 0) + values.insert(new FloatAnimationValue(0, startOpacity)); + values.insert(new FloatAnimationValue(duration, endOpacity)); + + RefPtr<Animation> animation = Animation::create(); + animation->setDuration(duration); + + IntSize boxSize; + + target.addAnimation(values, boxSize, animation.get(), 0, 0, 0); +} + +} // namespace + +namespace WebKitTests { + +FakeFloatAnimationCurve::FakeFloatAnimationCurve() +{ +} + +FakeFloatAnimationCurve::~FakeFloatAnimationCurve() +{ +} + +PassOwnPtr<WebCore::CCAnimationCurve> FakeFloatAnimationCurve::clone() const +{ + return adoptPtr(new FakeFloatAnimationCurve); +} + +FakeTransformTransition::FakeTransformTransition(double duration) + : m_duration(duration) +{ +} + +FakeTransformTransition::~FakeTransformTransition() +{ +} + +WebCore::TransformationMatrix FakeTransformTransition::getValue(double time, const WebCore::IntSize& size) const +{ + return WebCore::TransformationMatrix(); +} + +PassOwnPtr<WebCore::CCAnimationCurve> FakeTransformTransition::clone() const +{ + return adoptPtr(new FakeTransformTransition(*this)); +} + + +FakeFloatTransition::FakeFloatTransition(double duration, float from, float to) + : m_duration(duration) + , m_from(from) + , m_to(to) +{ +} + +FakeFloatTransition::~FakeFloatTransition() +{ +} + +float FakeFloatTransition::getValue(double time) const +{ + time /= m_duration; + if (time >= 1) + time = 1; + return (1 - time) * m_from + time * m_to; +} + +FakeLayerAnimationControllerImplClient::FakeLayerAnimationControllerImplClient() + : m_opacity(0) +{ +} + +FakeLayerAnimationControllerImplClient::~FakeLayerAnimationControllerImplClient() +{ +} + +PassOwnPtr<WebCore::CCAnimationCurve> FakeFloatTransition::clone() const +{ + return adoptPtr(new FakeFloatTransition(*this)); +} + +void addOpacityTransitionToController(WebCore::CCLayerAnimationController& controller, double duration, float startOpacity, float endOpacity) +{ + addOpacityTransition(controller, duration, startOpacity, endOpacity); +} + +void addOpacityTransitionToLayer(WebCore::LayerChromium& layer, double duration, float startOpacity, float endOpacity) +{ + addOpacityTransition(layer, duration, startOpacity, endOpacity); +} + +} // namespace WebKitTests diff --git a/Source/WebKit/chromium/tests/CCAnimationTestCommon.h b/Source/WebKit/chromium/tests/CCAnimationTestCommon.h new file mode 100644 index 000000000..d13e74ca1 --- /dev/null +++ b/Source/WebKit/chromium/tests/CCAnimationTestCommon.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCAnimationTestCommon_h +#define CCAnimationTestCommon_h + +#include "cc/CCAnimationCurve.h" +#include "cc/CCLayerAnimationControllerImpl.h" + +#include <wtf/OwnPtr.h> + +namespace WebCore { +class CCLayerAnimationController; +class LayerChromium; +} + +namespace WebKitTests { + +class FakeFloatAnimationCurve : public WebCore::CCFloatAnimationCurve { +public: + FakeFloatAnimationCurve(); + virtual ~FakeFloatAnimationCurve(); + + virtual double duration() const { return 1; } + virtual float getValue(double now) const { return 0; } + virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const; +}; + +class FakeTransformTransition : public WebCore::CCTransformAnimationCurve { +public: + FakeTransformTransition(double duration); + virtual ~FakeTransformTransition(); + + virtual double duration() const { return m_duration; } + virtual WebCore::TransformationMatrix getValue(double time, const WebCore::IntSize&) const; + + virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const; + +private: + double m_duration; +}; + +class FakeFloatTransition : public WebCore::CCFloatAnimationCurve { +public: + FakeFloatTransition(double duration, float from, float to); + virtual ~FakeFloatTransition(); + + virtual double duration() const { return m_duration; } + virtual float getValue(double time) const; + + virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const; + +private: + double m_duration; + float m_from; + float m_to; +}; + +class FakeLayerAnimationControllerImplClient : public WebCore::CCLayerAnimationControllerImplClient { +public: + FakeLayerAnimationControllerImplClient(); + virtual ~FakeLayerAnimationControllerImplClient(); + + virtual int id() const { return 0; } + virtual float opacity() const { return m_opacity; } + virtual void setOpacity(float opacity) { m_opacity = opacity; } + virtual const WebCore::TransformationMatrix& transform() const { return m_transform; } + virtual void setTransform(const WebCore::TransformationMatrix& transform) { m_transform = transform; } + virtual const WebCore::IntSize& bounds() const { return m_bounds; } + +private: + float m_opacity; + WebCore::TransformationMatrix m_transform; + WebCore::IntSize m_bounds; +}; + +void addOpacityTransitionToController(WebCore::CCLayerAnimationController&, double duration, float startOpacity, float endOpacity); + +void addOpacityTransitionToLayer(WebCore::LayerChromium&, double duration, float startOpacity, float endOpacity); + +} // namespace WebKitTests + +#endif // CCAnimationTesctCommon_h diff --git a/Source/WebKit/chromium/tests/CCKeyframedAnimationCurveTest.cpp b/Source/WebKit/chromium/tests/CCKeyframedAnimationCurveTest.cpp new file mode 100644 index 000000000..b7732aeab --- /dev/null +++ b/Source/WebKit/chromium/tests/CCKeyframedAnimationCurveTest.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "cc/CCKeyframedAnimationCurve.h" + +#include "Length.h" +#include "TranslateTransformOperation.h" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <wtf/OwnPtr.h> +#include <wtf/Vector.h> + +using namespace WebCore; + +namespace { + +void expectTranslateX(double translateX, const TransformationMatrix& matrix) +{ + TransformationMatrix::DecomposedType decomposedType; + matrix.decompose(decomposedType); + EXPECT_FLOAT_EQ(translateX, decomposedType.translateX); +} + +// Tests that a float animation with one keyframe works as expected. +TEST(CCKeyframedAnimationCurveTest, OneFloatKeyframe) +{ + Vector<CCFloatKeyframe> keyframes; + keyframes.append(CCFloatKeyframe(0, 2)); + OwnPtr<CCKeyframedFloatAnimationCurve> curve(CCKeyframedFloatAnimationCurve::create(keyframes)); + EXPECT_FLOAT_EQ(2, curve->getValue(-1)); + EXPECT_FLOAT_EQ(2, curve->getValue(0)); + EXPECT_FLOAT_EQ(2, curve->getValue(0.5)); + EXPECT_FLOAT_EQ(2, curve->getValue(1)); + EXPECT_FLOAT_EQ(2, curve->getValue(2)); +} + +// Tests that a float animation with two keyframes works as expected. +TEST(CCKeyframedAnimationCurveTest, TwoFloatKeyframe) +{ + Vector<CCFloatKeyframe> keyframes; + keyframes.append(CCFloatKeyframe(0, 2)); + keyframes.append(CCFloatKeyframe(1, 4)); + OwnPtr<CCKeyframedFloatAnimationCurve> curve(CCKeyframedFloatAnimationCurve::create(keyframes)); + EXPECT_FLOAT_EQ(2, curve->getValue(-1)); + EXPECT_FLOAT_EQ(2, curve->getValue(0)); + EXPECT_FLOAT_EQ(3, curve->getValue(0.5)); + EXPECT_FLOAT_EQ(4, curve->getValue(1)); + EXPECT_FLOAT_EQ(4, curve->getValue(2)); +} + +// Tests that a float animation with three keyframes works as expected. +TEST(CCKeyframedAnimationCurveTest, ThreeFloatKeyframe) +{ + Vector<CCFloatKeyframe> keyframes; + keyframes.append(CCFloatKeyframe(0, 2)); + keyframes.append(CCFloatKeyframe(1, 4)); + keyframes.append(CCFloatKeyframe(2, 8)); + OwnPtr<CCKeyframedFloatAnimationCurve> curve(CCKeyframedFloatAnimationCurve::create(keyframes)); + EXPECT_FLOAT_EQ(2, curve->getValue(-1)); + EXPECT_FLOAT_EQ(2, curve->getValue(0)); + EXPECT_FLOAT_EQ(3, curve->getValue(0.5)); + EXPECT_FLOAT_EQ(4, curve->getValue(1)); + EXPECT_FLOAT_EQ(6, curve->getValue(1.5)); + EXPECT_FLOAT_EQ(8, curve->getValue(2)); + EXPECT_FLOAT_EQ(8, curve->getValue(3)); +} + +// Tests that a float animation with multiple keys at a given time works sanely. +TEST(CCKeyframedAnimationCurveTest, RepeatedFloatKeyTimes) +{ + Vector<CCFloatKeyframe> keyframes; + // A step function. + keyframes.append(CCFloatKeyframe(0, 4)); + keyframes.append(CCFloatKeyframe(1, 4)); + keyframes.append(CCFloatKeyframe(1, 6)); + keyframes.append(CCFloatKeyframe(2, 6)); + OwnPtr<CCKeyframedFloatAnimationCurve> curve(CCKeyframedFloatAnimationCurve::create(keyframes)); + + EXPECT_FLOAT_EQ(4, curve->getValue(-1)); + EXPECT_FLOAT_EQ(4, curve->getValue(0)); + EXPECT_FLOAT_EQ(4, curve->getValue(0.5)); + + // There is a discontinuity at 1. Any value between 4 and 6 is valid. + float value = curve->getValue(1); + EXPECT_TRUE(value >= 4 && value <= 6); + + EXPECT_FLOAT_EQ(6, curve->getValue(1.5)); + EXPECT_FLOAT_EQ(6, curve->getValue(2)); + EXPECT_FLOAT_EQ(6, curve->getValue(3)); +} + + +// Tests that a transform animation with one keyframe works as expected. +TEST(CCKeyframedAnimationCurveTest, OneTransformKeyframe) +{ + Vector<CCTransformKeyframe> keyframes; + TransformOperations operations; + operations.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + keyframes.append(CCTransformKeyframe(0, operations)); + OwnPtr<CCKeyframedTransformAnimationCurve> curve(CCKeyframedTransformAnimationCurve::create(keyframes)); + IntSize layerSize; // ignored + expectTranslateX(2, curve->getValue(-1, layerSize)); + expectTranslateX(2, curve->getValue(0, layerSize)); + expectTranslateX(2, curve->getValue(0.5, layerSize)); + expectTranslateX(2, curve->getValue(1, layerSize)); + expectTranslateX(2, curve->getValue(2, layerSize)); +} + +// Tests that a transform animation with two keyframes works as expected. +TEST(CCKeyframedAnimationCurveTest, TwoTransformKeyframe) +{ + Vector<CCTransformKeyframe> keyframes; + TransformOperations operations1; + operations1.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + TransformOperations operations2; + operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + keyframes.append(CCTransformKeyframe(0, operations1)); + keyframes.append(CCTransformKeyframe(1, operations2)); + OwnPtr<CCKeyframedTransformAnimationCurve> curve(CCKeyframedTransformAnimationCurve::create(keyframes)); + IntSize layerSize; // ignored + expectTranslateX(2, curve->getValue(-1, layerSize)); + expectTranslateX(2, curve->getValue(0, layerSize)); + expectTranslateX(3, curve->getValue(0.5, layerSize)); + expectTranslateX(4, curve->getValue(1, layerSize)); + expectTranslateX(4, curve->getValue(2, layerSize)); +} + +// Tests that a transform animation with three keyframes works as expected. +TEST(CCKeyframedAnimationCurveTest, ThreeTransformKeyframe) +{ + Vector<CCTransformKeyframe> keyframes; + TransformOperations operations1; + operations1.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + TransformOperations operations2; + operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + TransformOperations operations3; + operations3.operations().append(TranslateTransformOperation::create(Length(8, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + keyframes.append(CCTransformKeyframe(0, operations1)); + keyframes.append(CCTransformKeyframe(1, operations2)); + keyframes.append(CCTransformKeyframe(2, operations3)); + OwnPtr<CCKeyframedTransformAnimationCurve> curve(CCKeyframedTransformAnimationCurve::create(keyframes)); + IntSize layerSize; // ignored + expectTranslateX(2, curve->getValue(-1, layerSize)); + expectTranslateX(2, curve->getValue(0, layerSize)); + expectTranslateX(3, curve->getValue(0.5, layerSize)); + expectTranslateX(4, curve->getValue(1, layerSize)); + expectTranslateX(6, curve->getValue(1.5, layerSize)); + expectTranslateX(8, curve->getValue(2, layerSize)); + expectTranslateX(8, curve->getValue(3, layerSize)); +} + +// Tests that a transform animation with multiple keys at a given time works sanely. +TEST(CCKeyframedAnimationCurveTest, RepeatedTransformKeyTimes) +{ + Vector<CCTransformKeyframe> keyframes; + // A step function. + TransformOperations operations1; + operations1.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + TransformOperations operations2; + operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + TransformOperations operations3; + operations3.operations().append(TranslateTransformOperation::create(Length(6, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + TransformOperations operations4; + operations4.operations().append(TranslateTransformOperation::create(Length(6, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + keyframes.append(CCTransformKeyframe(0, operations1)); + keyframes.append(CCTransformKeyframe(1, operations2)); + keyframes.append(CCTransformKeyframe(1, operations3)); + keyframes.append(CCTransformKeyframe(2, operations4)); + OwnPtr<CCKeyframedTransformAnimationCurve> curve(CCKeyframedTransformAnimationCurve::create(keyframes)); + + IntSize layerSize; // ignored + + expectTranslateX(4, curve->getValue(-1, layerSize)); + expectTranslateX(4, curve->getValue(0, layerSize)); + expectTranslateX(4, curve->getValue(0.5, layerSize)); + + // There is a discontinuity at 1. Any value between 4 and 6 is valid. + TransformationMatrix value = curve->getValue(1, layerSize); + TransformationMatrix::DecomposedType decomposedType; + value.decompose(decomposedType); + EXPECT_TRUE(decomposedType.translateX >= 4 && decomposedType.translateX <= 6); + + expectTranslateX(6, curve->getValue(1.5, layerSize)); + expectTranslateX(6, curve->getValue(2, layerSize)); + expectTranslateX(6, curve->getValue(3, layerSize)); +} + +// Tests that invalid lists of keyframes result in nothing being returned from ::create. +TEST(CCKeyframedAnimationCurveTest, InvalidKeyframes) +{ + // It is invalid to pass an empty vector of keyframes to create. + Vector<CCTransformKeyframe> transformKeyframes; + OwnPtr<CCKeyframedTransformAnimationCurve> transformCurve = CCKeyframedTransformAnimationCurve::create(transformKeyframes); + EXPECT_FALSE(transformCurve.get()); + + Vector<CCFloatKeyframe> floatKeyframes; + OwnPtr<CCKeyframedFloatAnimationCurve> floatCurve = CCKeyframedFloatAnimationCurve::create(floatKeyframes); + EXPECT_FALSE(floatCurve.get()); + + // It is invalid to pass a vector of unsorted keyframes to create; + TransformOperations operations1; + operations1.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + TransformOperations operations2; + operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + transformKeyframes.append(CCTransformKeyframe(1, operations1)); + transformKeyframes.append(CCTransformKeyframe(0, operations2)); + transformCurve = CCKeyframedTransformAnimationCurve::create(transformKeyframes); + EXPECT_FALSE(transformCurve.get()); + + floatKeyframes.append(CCFloatKeyframe(1, 2)); + floatKeyframes.append(CCFloatKeyframe(0, 4)); + floatCurve = CCKeyframedFloatAnimationCurve::create(floatKeyframes); + EXPECT_FALSE(floatCurve.get()); +} + + +} // namespace diff --git a/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp b/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp index 3d50d06e6..e1aeccc53 100644 --- a/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp +++ b/Source/WebKit/chromium/tests/CCLayerAnimationControllerImplTest.cpp @@ -24,92 +24,39 @@ #include "config.h" +#include "CCAnimationTestCommon.h" #include "cc/CCLayerAnimationControllerImpl.h" - -#include "TransformOperations.h" #include "cc/CCAnimationCurve.h" - +#include "cc/CCAnimationEvents.h" #include <gmock/gmock.h> #include <gtest/gtest.h> #include <wtf/Vector.h> using namespace WebCore; +using namespace WebKitTests; namespace { -class FakeControllerClient : public CCLayerAnimationControllerImplClient { -public: - FakeControllerClient() : m_opacity(0) { } - virtual ~FakeControllerClient() { } - - virtual float opacity() const { return m_opacity; } - virtual void setOpacity(float opacity) { m_opacity = opacity; } - virtual const TransformationMatrix& transform() const { return m_transform; } - virtual void setTransform(const TransformationMatrix& transform) { m_transform = transform; } - virtual void animationControllerImplDidActivate(CCLayerAnimationControllerImpl* controller) - { - m_activeControllers.append(controller); - } - - Vector<CCLayerAnimationControllerImpl*>& activeControllers() { return m_activeControllers; } - -private: - float m_opacity; - TransformationMatrix m_transform; - Vector<CCLayerAnimationControllerImpl*> m_activeControllers; -}; - -class FakeTransformTransition : public CCTransformAnimationCurve { -public: - FakeTransformTransition(double duration) : m_duration(duration) { } - virtual double duration() const { return m_duration; } - virtual TransformOperations getValue(double time) const - { - return TransformOperations(); - } - -private: - double m_duration; -}; - -class FakeFloatTransition : public CCFloatAnimationCurve { -public: - FakeFloatTransition(double duration, float from, float to) - : m_duration(duration) - , m_from(from) - , m_to(to) - { - } - - virtual double duration() const { return m_duration; } - virtual float getValue(double time) const - { - time /= m_duration; - if (time >= 1) - time = 1; - return (1 - time) * m_from + time * m_to; - } - -private: - double m_duration; - float m_from; - float m_to; -}; +PassOwnPtr<CCActiveAnimation> createActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, int id, CCActiveAnimation::TargetProperty property) +{ + return CCActiveAnimation::create(curve, 0, id, property); +} // Tests that transitioning opacity from 0 to 1 works as expected. TEST(CCLayerAnimationControllerImplTest, TrivialTransition) { - FakeControllerClient dummy; + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerImplClient dummy; OwnPtr<CCLayerAnimationControllerImpl> controller( CCLayerAnimationControllerImpl::create(&dummy)); - OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); controller->add(toAdd.release()); - controller->animate(0); + controller->animate(0, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); - controller->animate(1); + controller->animate(1, *events); EXPECT_EQ(1, dummy.opacity()); EXPECT_FALSE(controller->hasActiveAnimation()); } @@ -117,20 +64,21 @@ TEST(CCLayerAnimationControllerImplTest, TrivialTransition) // Tests that two queued animations affecting the same property run in sequence. TEST(CCLayerAnimationControllerImplTest, TrivialQueuing) { - FakeControllerClient dummy; + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerImplClient dummy; OwnPtr<CCLayerAnimationControllerImpl> controller( CCLayerAnimationControllerImpl::create(&dummy)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity)); - controller->animate(0); + controller->animate(0, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); - controller->animate(1); + controller->animate(1, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(1, dummy.opacity()); - controller->animate(2); + controller->animate(2, *events); EXPECT_EQ(0.5f, dummy.opacity()); EXPECT_FALSE(controller->hasActiveAnimation()); } @@ -138,22 +86,23 @@ TEST(CCLayerAnimationControllerImplTest, TrivialQueuing) // Tests interrupting a transition with another transition. TEST(CCLayerAnimationControllerImplTest, Interrupt) { - FakeControllerClient dummy; + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerImplClient dummy; OwnPtr<CCLayerAnimationControllerImpl> controller( CCLayerAnimationControllerImpl::create(&dummy)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); - controller->animate(0); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + controller->animate(0, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); - OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity)); + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity)); toAdd->setRunState(CCActiveAnimation::WaitingForNextTick, 0); controller->add(toAdd.release()); - controller->animate(0.5); // second anim starts NOW. + controller->animate(0.5, *events); // second anim starts NOW. EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(1, dummy.opacity()); - controller->animate(1.5); + controller->animate(1.5, *events); EXPECT_EQ(0.5f, dummy.opacity()); EXPECT_FALSE(controller->hasActiveAnimation()); } @@ -161,23 +110,24 @@ TEST(CCLayerAnimationControllerImplTest, Interrupt) // Tests scheduling two animations to run together when only one property is free. TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWhenAPropertyIsBlocked) { - FakeControllerClient dummy; + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerImplClient dummy; OwnPtr<CCLayerAnimationControllerImpl> controller( CCLayerAnimationControllerImpl::create(&dummy)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeTransformTransition(1)), 1, CCActiveAnimation::Transform)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeTransformTransition(1)), 2, CCActiveAnimation::Transform)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 2, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 1, CCActiveAnimation::Transform)); + controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 2, CCActiveAnimation::Transform)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 2, CCActiveAnimation::Opacity)); - controller->animate(0); + controller->animate(0, *events); EXPECT_EQ(0, dummy.opacity()); EXPECT_TRUE(controller->hasActiveAnimation()); - controller->animate(1); + controller->animate(1, *events); // Should not have started the float transition yet. EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); // The the float animation should have started at time 1 and should be done. - controller->animate(2); + controller->animate(2, *events); EXPECT_EQ(1, dummy.opacity()); EXPECT_FALSE(controller->hasActiveAnimation()); } @@ -187,29 +137,30 @@ TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWhenAPropertyIsBlocked) // for both to finish). TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWithAnAnimWaiting) { - FakeControllerClient dummy; + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerImplClient dummy; OwnPtr<CCLayerAnimationControllerImpl> controller( CCLayerAnimationControllerImpl::create(&dummy)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeTransformTransition(2)), 1, CCActiveAnimation::Transform)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(2)), 1, CCActiveAnimation::Transform)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity)); // Anims with id 1 should both start now. - controller->animate(0); + controller->animate(0, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); // The opacity animation should have finished at time 1, but the group // of animations with id 1 don't finish until time 2 because of the length // of the transform animation. - controller->animate(2); + controller->animate(2, *events); // Should not have started the float transition yet. EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(1, dummy.opacity()); // The the second opacity animation should start at time 2 and should be // done by time 3 - controller->animate(3); + controller->animate(3, *events); EXPECT_EQ(0.5f, dummy.opacity()); EXPECT_FALSE(controller->hasActiveAnimation()); } @@ -217,22 +168,23 @@ TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWithAnAnimWaiting) // Tests scheduling an animation to start in the future. TEST(CCLayerAnimationControllerImplTest, ScheduleAnimation) { - FakeControllerClient dummy; + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerImplClient dummy; OwnPtr<CCLayerAnimationControllerImpl> controller( CCLayerAnimationControllerImpl::create(&dummy)); - OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0); toAdd->setStartTime(1); controller->add(toAdd.release()); - controller->animate(0); + controller->animate(0, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); - controller->animate(1); + controller->animate(1, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); - controller->animate(2); + controller->animate(2, *events); EXPECT_EQ(1, dummy.opacity()); EXPECT_FALSE(controller->hasActiveAnimation()); } @@ -240,28 +192,29 @@ TEST(CCLayerAnimationControllerImplTest, ScheduleAnimation) // Tests scheduling an animation to start in the future that's interrupting a running animation. TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnimation) { - FakeControllerClient dummy; + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerImplClient dummy; OwnPtr<CCLayerAnimationControllerImpl> controller( CCLayerAnimationControllerImpl::create(&dummy)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity)); - OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0.5f, 0)), 2, CCActiveAnimation::Opacity)); + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0.5f, 0)), 2, CCActiveAnimation::Opacity)); toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0); toAdd->setStartTime(1); controller->add(toAdd.release()); // First 2s opacity transition should start immediately. - controller->animate(0); + controller->animate(0, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); - controller->animate(0.5); + controller->animate(0.5, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.25f, dummy.opacity()); - controller->animate(1); + controller->animate(1, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.5f, dummy.opacity()); - controller->animate(2); + controller->animate(2, *events); EXPECT_EQ(0, dummy.opacity()); EXPECT_FALSE(controller->hasActiveAnimation()); } @@ -270,34 +223,35 @@ TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnim // and there is yet another animation queued to start later. TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnimationWithAnimInQueue) { - FakeControllerClient dummy; + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerImplClient dummy; OwnPtr<CCLayerAnimationControllerImpl> controller( CCLayerAnimationControllerImpl::create(&dummy)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity)); - OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0.5f, 0)), 2, CCActiveAnimation::Opacity)); + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0.5f, 0)), 2, CCActiveAnimation::Opacity)); toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0); toAdd->setStartTime(1); controller->add(toAdd.release()); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 0.75f)), 3, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 0.75f)), 3, CCActiveAnimation::Opacity)); // First 2s opacity transition should start immediately. - controller->animate(0); + controller->animate(0, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); - controller->animate(0.5); + controller->animate(0.5, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.25f, dummy.opacity()); EXPECT_TRUE(controller->hasActiveAnimation()); - controller->animate(1); + controller->animate(1, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.5f, dummy.opacity()); - controller->animate(3); + controller->animate(3, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); - controller->animate(4); + controller->animate(4, *events); EXPECT_EQ(0.75f, dummy.opacity()); EXPECT_FALSE(controller->hasActiveAnimation()); } @@ -305,64 +259,66 @@ TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnim // Test that a looping animation loops and for the correct number of iterations. TEST(CCLayerAnimationControllerImplTest, TrivialLooping) { - FakeControllerClient dummy; + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerImplClient dummy; OwnPtr<CCLayerAnimationControllerImpl> controller( CCLayerAnimationControllerImpl::create(&dummy)); - OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); toAdd->setIterations(3); controller->add(toAdd.release()); - controller->animate(0); + controller->animate(0, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); - controller->animate(1.25); + controller->animate(1.25, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.25f, dummy.opacity()); - controller->animate(1.75); + controller->animate(1.75, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.75f, dummy.opacity()); - controller->animate(2.25); + controller->animate(2.25, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.25f, dummy.opacity()); - controller->animate(2.75); + controller->animate(2.75, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.75f, dummy.opacity()); - controller->animate(3); + controller->animate(3, *events); EXPECT_FALSE(controller->hasActiveAnimation()); EXPECT_EQ(1, dummy.opacity()); // Just be extra sure. - controller->animate(4); + controller->animate(4, *events); EXPECT_EQ(1, dummy.opacity()); } // Test that an infinitely looping animation does indeed go until aborted. TEST(CCLayerAnimationControllerImplTest, InfiniteLooping) { - FakeControllerClient dummy; + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerImplClient dummy; OwnPtr<CCLayerAnimationControllerImpl> controller( CCLayerAnimationControllerImpl::create(&dummy)); const int id = 1; - OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity)); + OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity)); toAdd->setIterations(-1); controller->add(toAdd.release()); - controller->animate(0); + controller->animate(0, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); - controller->animate(1.25); + controller->animate(1.25, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.25f, dummy.opacity()); - controller->animate(1.75); + controller->animate(1.75, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.75f, dummy.opacity()); - controller->animate(1073741824.25); + controller->animate(1073741824.25, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.25f, dummy.opacity()); - controller->animate(1073741824.75); + controller->animate(1073741824.75, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.75f, dummy.opacity()); @@ -375,80 +331,66 @@ TEST(CCLayerAnimationControllerImplTest, InfiniteLooping) // Test that pausing and resuming work as expected. TEST(CCLayerAnimationControllerImplTest, PauseResume) { - FakeControllerClient dummy; + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerImplClient dummy; OwnPtr<CCLayerAnimationControllerImpl> controller( CCLayerAnimationControllerImpl::create(&dummy)); const int id = 1; - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity)); - controller->animate(0); + controller->animate(0, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); - controller->animate(0.5); + controller->animate(0.5, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.5f, dummy.opacity()); EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity)); controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Paused, 0.5f); - controller->animate(1024); + controller->animate(1024, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.5f, dummy.opacity()); EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity)); controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Running, 1024); - controller->animate(1024.25); + controller->animate(1024.25, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.75f, dummy.opacity()); - controller->animate(1024.5); + controller->animate(1024.5, *events); EXPECT_FALSE(controller->hasActiveAnimation()); EXPECT_EQ(1, dummy.opacity()); } TEST(CCLayerAnimationControllerImplTest, AbortAGroupedAnimation) { - FakeControllerClient dummy; + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + FakeLayerAnimationControllerImplClient dummy; OwnPtr<CCLayerAnimationControllerImpl> controller( CCLayerAnimationControllerImpl::create(&dummy)); const int id = 1; - controller->add(CCActiveAnimation::create(adoptPtr(new FakeTransformTransition(1)), id, CCActiveAnimation::Transform)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0, 1)), id, CCActiveAnimation::Opacity)); - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 1, 0.75f)), 2, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), id, CCActiveAnimation::Transform)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), id, CCActiveAnimation::Opacity)); + controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.75f)), 2, CCActiveAnimation::Opacity)); - controller->animate(0); + controller->animate(0, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0, dummy.opacity()); - controller->animate(1); + controller->animate(1, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(0.5f, dummy.opacity()); EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity)); controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 1); - controller->animate(1); + controller->animate(1, *events); EXPECT_TRUE(controller->hasActiveAnimation()); EXPECT_EQ(1, dummy.opacity()); - controller->animate(2); + controller->animate(2, *events); EXPECT_TRUE(!controller->hasActiveAnimation()); EXPECT_EQ(0.75f, dummy.opacity()); } -// Tests that adding an animation to the controller calls the appropriate callback on the controller client -// (in this case, adding the controller to the list of active controller). -TEST(CCLayerAnimationControllerImplTest, DidActivate) -{ - FakeControllerClient dummy; - OwnPtr<CCLayerAnimationControllerImpl> controller( - CCLayerAnimationControllerImpl::create(&dummy)); - - EXPECT_EQ(size_t(0), dummy.activeControllers().size()); - - controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity)); - - EXPECT_EQ(size_t(1), dummy.activeControllers().size()); - EXPECT_EQ(controller.get(), dummy.activeControllers()[0]); -} - } // namespace diff --git a/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp b/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp new file mode 100644 index 000000000..c4f103a3c --- /dev/null +++ b/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "cc/CCLayerAnimationController.h" + +#include "CCAnimationTestCommon.h" +#include "GraphicsLayer.h" +#include "Length.h" +#include "TranslateTransformOperation.h" +#include "cc/CCActiveAnimation.h" +#include "cc/CCAnimationCurve.h" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <wtf/Vector.h> + +using namespace WebCore; +using namespace WebKitTests; + +namespace { + +void expectTranslateX(double translateX, const TransformationMatrix& matrix) +{ + TransformationMatrix::DecomposedType decomposedType; + matrix.decompose(decomposedType); + EXPECT_FLOAT_EQ(translateX, decomposedType.translateX); +} + +PassOwnPtr<CCActiveAnimation> createActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, int id, CCActiveAnimation::TargetProperty property) +{ + return CCActiveAnimation::create(curve, 0, id, property); +} + +TEST(CCLayerAnimationControllerTest, createOpacityAnimation) +{ + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create()); + const double duration = 1; + WebCore::KeyframeValueList values(AnimatedPropertyOpacity); + values.insert(new FloatAnimationValue(0, 0)); + values.insert(new FloatAnimationValue(duration, 1)); + + RefPtr<Animation> animation = Animation::create(); + animation->setDuration(duration); + + IntSize boxSize; + controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0); + + EXPECT_TRUE(controller->hasActiveAnimation()); + + CCActiveAnimation* activeAnimation = controller->getActiveAnimation(0, CCActiveAnimation::Opacity); + EXPECT_TRUE(activeAnimation); + + EXPECT_EQ(1, activeAnimation->iterations()); + EXPECT_EQ(CCActiveAnimation::Opacity, activeAnimation->targetProperty()); + + EXPECT_EQ(CCAnimationCurve::Float, activeAnimation->curve()->type()); + + const CCFloatAnimationCurve* curve = activeAnimation->curve()->toFloatAnimationCurve(); + EXPECT_TRUE(curve); + + EXPECT_EQ(0, curve->getValue(0)); + EXPECT_EQ(1, curve->getValue(duration)); +} + +TEST(CCLayerAnimationControllerTest, createTransformAnimation) +{ + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create()); + const double duration = 1; + WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform); + + TransformOperations operations1; + operations1.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + values.insert(new TransformAnimationValue(0, &operations1)); + + TransformOperations operations2; + operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X)); + values.insert(new TransformAnimationValue(duration, &operations2)); + + RefPtr<Animation> animation = Animation::create(); + animation->setDuration(duration); + + IntSize boxSize; + controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0); + + EXPECT_TRUE(controller->hasActiveAnimation()); + + CCActiveAnimation* activeAnimation = controller->getActiveAnimation(0, CCActiveAnimation::Transform); + EXPECT_TRUE(activeAnimation); + + EXPECT_EQ(1, activeAnimation->iterations()); + EXPECT_EQ(CCActiveAnimation::Transform, activeAnimation->targetProperty()); + + EXPECT_EQ(CCAnimationCurve::Transform, activeAnimation->curve()->type()); + + const CCTransformAnimationCurve* curve = activeAnimation->curve()->toTransformAnimationCurve(); + EXPECT_TRUE(curve); + + expectTranslateX(2, curve->getValue(0, boxSize)); + expectTranslateX(4, curve->getValue(duration, boxSize)); +} + +TEST(CCLayerAnimationControllerTest, syncNewAnimation) +{ + FakeLayerAnimationControllerImplClient dummy; + OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy)); + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create()); + + EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); + + addOpacityTransitionToController(*controller, 1, 0, 1); + + controller->synchronizeAnimations(controllerImpl.get()); + + EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); + EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); +} + +TEST(CCLayerAnimationControllerTest, syncAnimationProperties) +{ + FakeLayerAnimationControllerImplClient dummy; + OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy)); + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create()); + + EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); + + addOpacityTransitionToController(*controller, 1, 0, 1); + + controller->synchronizeAnimations(controllerImpl.get()); + + EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); + EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); + + // Push an animation property change to the impl thread (should not cause an animation to be added). + controller->pauseAnimation(0, 0); + controller->synchronizeAnimations(controllerImpl.get()); + + EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); + EXPECT_EQ(CCActiveAnimation::Paused, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); +} + +TEST(CCLayerAnimationControllerTest, syncAbortedAnimation) +{ + FakeLayerAnimationControllerImplClient dummy; + OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy)); + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create()); + + EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); + + addOpacityTransitionToController(*controller, 1, 0, 1); + + controller->synchronizeAnimations(controllerImpl.get()); + + EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); + EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); + + controller->removeAnimation(0); + + // Abort an animation from the main thread. + controller->synchronizeAnimations(controllerImpl.get()); + + EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); +} + +TEST(CCLayerAnimationControllerTest, syncCompletedAnimation) +{ + FakeLayerAnimationControllerImplClient dummy; + OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy)); + OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create()); + + EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); + + addOpacityTransitionToController(*controller, 1, 0, 1); + + controller->synchronizeAnimations(controllerImpl.get()); + + EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); + EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState()); + + // Step through the animation until it is finished. At the next sync, the main thread's animation should be cleared. + OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); + controllerImpl->animate(0, *events); + controllerImpl->animate(2, *events); + + EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)); + EXPECT_TRUE(controller->hasActiveAnimation()); + + controller->synchronizeAnimations(controllerImpl.get()); + + EXPECT_FALSE(controller->hasActiveAnimation()); +} + +} // namespace diff --git a/Source/WebKit/chromium/tests/CCLayerImplTest.cpp b/Source/WebKit/chromium/tests/CCLayerImplTest.cpp index 27728cbef..16a25e12e 100644 --- a/Source/WebKit/chromium/tests/CCLayerImplTest.cpp +++ b/Source/WebKit/chromium/tests/CCLayerImplTest.cpp @@ -88,10 +88,13 @@ TEST(CCLayerImplTest, verifyLayerChangesAreTrackedProperly) Color arbitraryColor = Color(10, 20, 30); TransformationMatrix arbitraryTransform; arbitraryTransform.scale3d(0.1, 0.2, 0.3); + FilterOperations arbitraryFilters; + arbitraryFilters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::OPACITY)); // Changing these properties affects the entire subtree of layers. EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setAnchorPoint(arbitraryFloatPoint)); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setAnchorPointZ(arbitraryNumber)); + EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setFilters(arbitraryFilters)); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setMaskLayer(dummyMask)); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setMasksToBounds(true)); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setOpaque(true)); diff --git a/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp b/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp index b1fa72918..d2e1cfef9 100644 --- a/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp +++ b/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp @@ -28,7 +28,6 @@ #include "CCLayerTreeTestCommon.h" #include "LayerChromium.h" -#include "Region.h" #include "TransformationMatrix.h" #include <gmock/gmock.h> @@ -36,12 +35,6 @@ using namespace WebCore; -#define EXPECT_EQ_RECT(a, b) \ - EXPECT_EQ(a.x(), b.x()); \ - EXPECT_EQ(a.y(), b.y()); \ - EXPECT_EQ(a.width(), b.width()); \ - EXPECT_EQ(a.height(), b.height()); - namespace { void setLayerPropertiesForTesting(LayerChromium* layer, const TransformationMatrix& transform, const TransformationMatrix& sublayerTransform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool preserves3D) @@ -602,174 +595,4 @@ TEST(CCLayerTreeHostCommonTest, verifyClipRectCullsRenderSurfaces) // - test the other functions in CCLayerTreeHostCommon // -TEST(CCLayerTreeHostCommonTest, layerAddsSelfToOccludedRegion) -{ - // This tests that the right transforms are being used. - Region occluded; - const TransformationMatrix identityMatrix; - RefPtr<LayerChromium> parent = LayerChromium::create(); - RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent()); - parent->createRenderSurface(); - parent->addChild(layer); - - setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); - setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false); - - layer->setOpaque(true); - - Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; - Vector<RefPtr<LayerChromium> > dummyLayerList; - int dummyMaxTextureSize = 512; - - // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too. - parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); - parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); - renderSurfaceLayerList.append(parent); - - CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); - - occluded = Region(); - layer->addSelfToOccludedScreenSpace(occluded); - EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occluded.bounds()); - EXPECT_EQ(1u, occluded.rects().size()); -} - -TEST(CCLayerTreeHostCommonTest, layerAddsSelfToOccludedRegionWithRotation) -{ - // This tests that the right transforms are being used. - Region occluded; - const TransformationMatrix identityMatrix; - RefPtr<LayerChromium> parent = LayerChromium::create(); - RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent()); - parent->createRenderSurface(); - parent->addChild(layer); - - TransformationMatrix layerTransform; - layerTransform.translate(250, 250); - layerTransform.rotate(90); - layerTransform.translate(-250, -250); - - setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); - setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false); - - layer->setOpaque(true); - - Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; - Vector<RefPtr<LayerChromium> > dummyLayerList; - int dummyMaxTextureSize = 512; - - // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too. - parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); - parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); - renderSurfaceLayerList.append(parent); - - CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); - - occluded = Region(); - layer->addSelfToOccludedScreenSpace(occluded); - EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occluded.bounds()); - EXPECT_EQ(1u, occluded.rects().size()); -} - -TEST(CCLayerTreeHostCommonTest, layerAddsSelfToOccludedRegionWithTranslation) -{ - // This tests that the right transforms are being used. - Region occluded; - const TransformationMatrix identityMatrix; - RefPtr<LayerChromium> parent = LayerChromium::create(); - RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent()); - parent->createRenderSurface(); - parent->addChild(layer); - - TransformationMatrix layerTransform; - layerTransform.translate(20, 20); - - setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); - setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false); - - layer->setOpaque(true); - - Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; - Vector<RefPtr<LayerChromium> > dummyLayerList; - int dummyMaxTextureSize = 512; - - // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too. - parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); - parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); - renderSurfaceLayerList.append(parent); - - CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); - - occluded = Region(); - layer->addSelfToOccludedScreenSpace(occluded); - EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occluded.bounds()); - EXPECT_EQ(1u, occluded.rects().size()); -} - -TEST(CCLayerTreeHostCommonTest, layerAddsSelfToOccludedRegionWithRotatedSurface) -{ - // This tests that the right transforms are being used. - Region occluded; - const TransformationMatrix identityMatrix; - RefPtr<LayerChromium> parent = LayerChromium::create(); - RefPtr<LayerChromium> child = LayerChromium::create(); - RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent()); - parent->createRenderSurface(); - parent->addChild(child); - child->addChild(layer); - - TransformationMatrix childTransform; - childTransform.translate(250, 250); - childTransform.rotate(90); - childTransform.translate(-250, -250); - - setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); - setLayerPropertiesForTesting(child.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false); - setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), false); - - child->setMasksToBounds(true); - layer->setOpaque(true); - - Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; - Vector<RefPtr<LayerChromium> > dummyLayerList; - int dummyMaxTextureSize = 512; - - // FIXME: when we fix this "root-layer special case" behavior in CCLayerTreeHost, we will have to fix it here, too. - parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); - parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); - renderSurfaceLayerList.append(parent); - - CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); - - occluded = Region(); - layer->addSelfToOccludedScreenSpace(occluded); - EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occluded.bounds()); - EXPECT_EQ(1u, occluded.rects().size()); - - /* Justification for the above opaque rect from |layer|: - 100 - +---------------------+ +---------------------+ - | | | |30 Visible region of |layer|: ///// - | 30 | rotate(90) | | - | 30 + ---------------------------------+ | +---------------------------------+ - 100 | | 10 | | ==> | | |10 | - | |10+---------------------------------+ | +---------------------------------+ | - | | | | | | | | |///////////////| 420 | | - | | | | | | | | |///////////////|60 | | - | | | | | | | | |///////////////| | | - +----|--|-------------+ | | +--|--|---------------+ | | - | | | | 20|10| 70 | | - | | | | | | | | - | | | |500 | | | | - | | | | | | | | - | | | | | | | | - | | | | | | | | - | | | | | | |10| - +--|-------------------------------+ | | +------------------------------|--+ - | | | 490 | - +---------------------------------+ +---------------------------------+ - 500 500 - */ -} - } // namespace diff --git a/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp b/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp index f59893de9..9ba1cf4ad 100644 --- a/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp +++ b/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp @@ -52,6 +52,7 @@ public: virtual void onSwapBuffersCompleteOnImplThread() { } virtual void setNeedsRedrawOnImplThread() { m_didRequestRedraw = true; } virtual void setNeedsCommitOnImplThread() { m_didRequestCommit = true; } + virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>) { } static void expectClearedScrollDeltasRecursive(CCLayerImpl* layer) { @@ -67,7 +68,8 @@ public: for (size_t i = 0; i < scrollInfo.scrolls.size(); ++i) { if (scrollInfo.scrolls[i].layerId != id) continue; - ASSERT_EQ(scrollInfo.scrolls[i].scrollDelta, scrollDelta); + EXPECT_EQ(scrollDelta.width(), scrollInfo.scrolls[i].scrollDelta.width()); + EXPECT_EQ(scrollDelta.height(), scrollInfo.scrolls[i].scrollDelta.height()); timesEncountered++; } @@ -89,6 +91,11 @@ public: } protected: + PassRefPtr<GraphicsContext3D> createContext() + { + return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FakeWebGraphicsContext3D()), GraphicsContext3D::RenderDirectlyToHostWindow); + } + DebugScopedSetImplThread m_alwaysImplThread; OwnPtr<CCLayerTreeHostImpl> m_hostImpl; bool m_didRequestCommit; @@ -142,14 +149,14 @@ TEST_F(CCLayerTreeHostImplTest, scrollDeltaRepeatedScrolls) scrollInfo = m_hostImpl->processScrollDeltas(); ASSERT_EQ(scrollInfo->scrolls.size(), 1u); EXPECT_EQ(root->sentScrollDelta(), scrollDelta); - expectContains(*scrollInfo.get(), root->id(), scrollDelta); + expectContains(*scrollInfo, root->id(), scrollDelta); IntSize scrollDelta2(-5, 27); root->scrollBy(scrollDelta2); scrollInfo = m_hostImpl->processScrollDeltas(); ASSERT_EQ(scrollInfo->scrolls.size(), 1u); EXPECT_EQ(root->sentScrollDelta(), scrollDelta + scrollDelta2); - expectContains(*scrollInfo.get(), root->id(), scrollDelta + scrollDelta2); + expectContains(*scrollInfo, root->id(), scrollDelta + scrollDelta2); root->scrollBy(IntSize()); scrollInfo = m_hostImpl->processScrollDeltas(); @@ -163,13 +170,28 @@ TEST_F(CCLayerTreeHostImplTest, scrollRootCallsCommitAndRedraw) root->setScrollPosition(IntPoint(0, 0)); root->setMaxScrollPosition(IntSize(100, 100)); m_hostImpl->setRootLayer(root); - EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0)), CCInputHandlerClient::ScrollStarted); + EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted); m_hostImpl->scrollBy(IntSize(0, 10)); m_hostImpl->scrollEnd(); EXPECT_TRUE(m_didRequestRedraw); EXPECT_TRUE(m_didRequestCommit); } +TEST_F(CCLayerTreeHostImplTest, wheelEventHandlers) +{ + RefPtr<CCLayerImpl> root = CCLayerImpl::create(0); + root->setScrollable(true); + root->setScrollPosition(IntPoint(0, 0)); + root->setMaxScrollPosition(IntSize(100, 100)); + m_hostImpl->setRootLayer(root); + root->setHaveWheelEventHandlers(true); + // With registered event handlers, wheel scrolls have to go to the main thread. + EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed); + + // But gesture scrolls can still be handled. + EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted); +} + TEST_F(CCLayerTreeHostImplTest, pinchGesture) { setupScrollAndContentsLayers(IntSize(100, 100)); @@ -184,6 +206,7 @@ TEST_F(CCLayerTreeHostImplTest, pinchGesture) { m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale); scrollLayer->setPageScaleDelta(1); + scrollLayer->setScrollDelta(IntSize()); float pageScaleDelta = 2; m_hostImpl->pinchGestureBegin(); @@ -200,6 +223,7 @@ TEST_F(CCLayerTreeHostImplTest, pinchGesture) { m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale); scrollLayer->setPageScaleDelta(1); + scrollLayer->setScrollDelta(IntSize()); float pageScaleDelta = 10; m_hostImpl->pinchGestureBegin(); @@ -214,6 +238,7 @@ TEST_F(CCLayerTreeHostImplTest, pinchGesture) { m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale); scrollLayer->setPageScaleDelta(1); + scrollLayer->setScrollDelta(IntSize()); scrollLayer->setScrollPosition(IntPoint(50, 50)); float pageScaleDelta = 0.1; @@ -225,7 +250,25 @@ TEST_F(CCLayerTreeHostImplTest, pinchGesture) EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale); // Pushed to (0,0) via clamping against contents layer size. - expectContains(*scrollInfo.get(), scrollLayer->id(), IntSize(-50, -50)); + expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50)); + } + + // Two-finger panning + { + m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale); + scrollLayer->setPageScaleDelta(1); + scrollLayer->setScrollDelta(IntSize()); + scrollLayer->setScrollPosition(IntPoint(20, 20)); + + float pageScaleDelta = 1; + m_hostImpl->pinchGestureBegin(); + m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(10, 10)); + m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(20, 20)); + m_hostImpl->pinchGestureEnd(); + + OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas(); + EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta); + expectContains(*scrollInfo, scrollLayer->id(), IntSize(-10, -10)); } } @@ -255,7 +298,7 @@ TEST_F(CCLayerTreeHostImplTest, pageScaleAnimation) OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas(); EXPECT_EQ(scrollInfo->pageScaleDelta, 2); - expectContains(*scrollInfo.get(), scrollLayer->id(), IntSize(-50, -50)); + expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50)); } // Anchor zoom-out @@ -272,8 +315,107 @@ TEST_F(CCLayerTreeHostImplTest, pageScaleAnimation) OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas(); EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale); // Pushed to (0,0) via clamping against contents layer size. - expectContains(*scrollInfo.get(), scrollLayer->id(), IntSize(-50, -50)); + expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50)); + } +} + +class DidDrawCheckLayer : public CCLayerImpl { +public: + static PassRefPtr<DidDrawCheckLayer> create(int id) { return adoptRef(new DidDrawCheckLayer(id)); } + + virtual void didDraw() + { + m_didDrawCalled = true; + } + + virtual void willDraw(LayerRendererChromium*) + { + m_willDrawCalled = true; + } + + bool didDrawCalled() const { return m_didDrawCalled; } + bool willDrawCalled() const { return m_willDrawCalled; } + +private: + explicit DidDrawCheckLayer(int id) + : CCLayerImpl(id) + , m_didDrawCalled(false) + , m_willDrawCalled(false) + { + setAnchorPoint(FloatPoint(0, 0)); + setBounds(IntSize(10, 10)); + setDrawsContent(true); } + + bool m_didDrawCalled; + bool m_willDrawCalled; +}; + +TEST_F(CCLayerTreeHostImplTest, didDrawNotCalledOnHiddenLayer) +{ + RefPtr<GraphicsContext3D> context = createContext(); + m_hostImpl->initializeLayerRenderer(context); + + // Ensure visibleLayerRect for root layer is empty + m_hostImpl->setViewportSize(IntSize(0, 0)); + + RefPtr<DidDrawCheckLayer> root = DidDrawCheckLayer::create(0); + m_hostImpl->setRootLayer(root); + + EXPECT_FALSE(root->willDrawCalled()); + EXPECT_FALSE(root->didDrawCalled()); + + m_hostImpl->drawLayers(); + + EXPECT_FALSE(root->willDrawCalled()); + EXPECT_FALSE(root->didDrawCalled()); + + EXPECT_TRUE(root->visibleLayerRect().isEmpty()); + + // Ensure visibleLayerRect for root layer is not empty + m_hostImpl->setViewportSize(IntSize(10, 10)); + + EXPECT_FALSE(root->willDrawCalled()); + EXPECT_FALSE(root->didDrawCalled()); + + m_hostImpl->drawLayers(); + + EXPECT_TRUE(root->willDrawCalled()); + EXPECT_TRUE(root->didDrawCalled()); + + EXPECT_FALSE(root->visibleLayerRect().isEmpty()); +} + +TEST_F(CCLayerTreeHostImplTest, didDrawCalledOnAllLayers) +{ + RefPtr<GraphicsContext3D> context = createContext(); + m_hostImpl->initializeLayerRenderer(context); + m_hostImpl->setViewportSize(IntSize(10, 10)); + + RefPtr<DidDrawCheckLayer> root = DidDrawCheckLayer::create(0); + m_hostImpl->setRootLayer(root); + + RefPtr<DidDrawCheckLayer> layer1 = DidDrawCheckLayer::create(1); + root->addChild(layer1); + + RefPtr<DidDrawCheckLayer> layer2 = DidDrawCheckLayer::create(2); + layer1->addChild(layer2); + + layer1->setOpacity(0.3); + layer1->setPreserves3D(false); + + EXPECT_FALSE(root->didDrawCalled()); + EXPECT_FALSE(layer1->didDrawCalled()); + EXPECT_FALSE(layer2->didDrawCalled()); + + m_hostImpl->drawLayers(); + + EXPECT_TRUE(root->didDrawCalled()); + EXPECT_TRUE(layer1->didDrawCalled()); + EXPECT_TRUE(layer2->didDrawCalled()); + + EXPECT_NE(root->renderSurface(), layer1->renderSurface()); + EXPECT_TRUE(!!layer1->renderSurface()); } class BlendStateTrackerContext: public FakeWebGraphicsContext3D { @@ -347,8 +489,7 @@ private: // https://bugs.webkit.org/show_bug.cgi?id=75783 TEST_F(CCLayerTreeHostImplTest, blendingOffWhenDrawingOpaqueLayers) { - GraphicsContext3D::Attributes attrs; - RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new BlendStateTrackerContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread); + RefPtr<GraphicsContext3D> context = createContext(); m_hostImpl->initializeLayerRenderer(context); m_hostImpl->setViewportSize(IntSize(10, 10)); @@ -507,7 +648,6 @@ private: class FakeDrawableCCLayerImpl: public CCLayerImpl { public: explicit FakeDrawableCCLayerImpl(int id) : CCLayerImpl(id) { } - virtual void draw(LayerRendererChromium* renderer) { } }; // Only reshape when we know we are going to draw. Otherwise, the reshape @@ -515,9 +655,8 @@ public: // viewport size is never set. TEST_F(CCLayerTreeHostImplTest, reshapeNotCalledUntilDraw) { - GraphicsContext3D::Attributes attrs; ReshapeTrackerContext* reshapeTracker = new ReshapeTrackerContext(); - RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(reshapeTracker), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread); + RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(reshapeTracker), GraphicsContext3D::RenderDirectlyToHostWindow); m_hostImpl->initializeLayerRenderer(context); m_hostImpl->setViewportSize(IntSize(10, 10)); @@ -559,9 +698,8 @@ private: // where it should request to swap only the subBuffer that is damaged. TEST_F(CCLayerTreeHostImplTest, partialSwapReceivesDamageRect) { - GraphicsContext3D::Attributes attrs; PartialSwapTrackerContext* partialSwapTracker = new PartialSwapTrackerContext(); - RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(partialSwapTracker), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread); + RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(partialSwapTracker), GraphicsContext3D::RenderDirectlyToHostWindow); // This test creates its own CCLayerTreeHostImpl, so // that we can force partial swap enabled. diff --git a/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp b/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp index fc414f739..10cfa6931 100644 --- a/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp +++ b/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp @@ -26,14 +26,18 @@ #include "cc/CCLayerTreeHost.h" +#include "CCAnimationTestCommon.h" #include "CompositorFakeWebGraphicsContext3D.h" #include "ContentLayerChromium.h" +#include "FilterOperations.h" #include "GraphicsContext3DPrivate.h" #include "LayerChromium.h" #include "Region.h" #include "TextureManager.h" #include "WebCompositor.h" #include "WebKit.h" +#include "cc/CCActiveAnimation.h" +#include "cc/CCLayerAnimationController.h" #include "cc/CCLayerImpl.h" #include "cc/CCLayerTreeHostImpl.h" #include "cc/CCScopedThreadProxy.h" @@ -49,6 +53,7 @@ using namespace WebCore; using namespace WebKit; +using namespace WebKitTests; using namespace WTF; namespace { @@ -59,6 +64,7 @@ public: virtual void beginCommitOnCCThread(CCLayerTreeHostImpl*) { } virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*) { } virtual void drawLayersOnCCThread(CCLayerTreeHostImpl*) { } + virtual void animateLayers(CCLayerTreeHostImpl*) { } virtual void applyScrollAndScale(const IntSize&, float) { } virtual void updateAnimations(double frameBeginTime) { } virtual void layout() { } @@ -90,6 +96,13 @@ public: m_testHooks->drawLayersOnCCThread(this); } +protected: + virtual void animateLayers(double frameBeginTimeMs) + { + CCLayerTreeHostImpl::animateLayers(frameBeginTimeMs); + m_testHooks->animateLayers(this); + } + private: MockLayerTreeHostImpl(TestHooks* testHooks, const CCSettings& settings, CCLayerTreeHostImplClient* client) : CCLayerTreeHostImpl(settings, client) @@ -105,7 +118,11 @@ class MockLayerTreeHost : public CCLayerTreeHost { public: static PassRefPtr<MockLayerTreeHost> create(TestHooks* testHooks, CCLayerTreeHostClient* client, PassRefPtr<LayerChromium> rootLayer, const CCSettings& settings) { - RefPtr<MockLayerTreeHost> layerTreeHost = adoptRef(new MockLayerTreeHost(testHooks, client, settings)); + // For these tests, we will enable threaded animations. + CCSettings settingsCopy = settings; + settingsCopy.threadedAnimationEnabled = true; + + RefPtr<MockLayerTreeHost> layerTreeHost = adoptRef(new MockLayerTreeHost(testHooks, client, settingsCopy)); bool success = layerTreeHost->initialize(); EXPECT_TRUE(success); layerTreeHost->setRootLayer(rootLayer); @@ -118,7 +135,10 @@ public: virtual PassOwnPtr<CCLayerTreeHostImpl> createLayerTreeHostImpl(CCLayerTreeHostImplClient* client) { - return MockLayerTreeHostImpl::create(m_testHooks, settings(), client); + // For these tests, we will enable threaded animations. + CCSettings settings; + settings.threadedAnimationEnabled = true; + return MockLayerTreeHostImpl::create(m_testHooks, settings, client); } private: @@ -207,10 +227,7 @@ public: webAttrs.alpha = attrs.alpha; OwnPtr<WebGraphicsContext3D> webContext = CompositorFakeWebGraphicsContext3DWithTextureTracking::create(webAttrs); - return GraphicsContext3DPrivate::createGraphicsContextFromWebContext( - webContext.release(), attrs, 0, - GraphicsContext3D::RenderDirectlyToHostWindow, - GraphicsContext3DPrivate::ForUseOnAnotherThread); + return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(webContext.release(), GraphicsContext3D::RenderDirectlyToHostWindow); } virtual void didCommitAndDrawFrame() @@ -225,7 +242,9 @@ public: { } - virtual void scheduleComposite() { } + virtual void scheduleComposite() + { + } private: explicit MockLayerTreeHostClient(TestHooks* testHooks) : m_testHooks(testHooks) { } @@ -255,6 +274,11 @@ public: callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsAnimate, this); } + void postAddAnimationToMainThread() + { + callOnMainThread(CCLayerTreeHostTest::dispatchAddAnimation, this); + } + void postSetNeedsCommitToMainThread() { callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsCommit, this); @@ -270,7 +294,6 @@ public: callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsAnimateAndCommit, this); } - void postSetVisibleToMainThread(bool visible) { callOnMainThread(visible ? CCLayerTreeHostTest::dispatchSetVisible : CCLayerTreeHostTest::dispatchSetInvisible, this); @@ -313,6 +336,15 @@ protected: test->m_layerTreeHost->setNeedsAnimate(); } + static void dispatchAddAnimation(void* self) + { + ASSERT(isMainThread()); + CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self); + ASSERT(test); + if (test->m_layerTreeHost && test->m_layerTreeHost->rootLayer()) + addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 0, 0, 1); + } + static void dispatchSetNeedsAnimateAndCommit(void* self) { ASSERT(isMainThread()); @@ -789,6 +821,47 @@ TEST_F(CCLayerTreeHostTestSetNeedsAnimateInsideAnimationCallback, runMultiThread runTestThreaded(); } +// Add a layer animation and confirm that CCLayerTreeHostImpl::animateLayers does get +// called and continues to get called. +class CCLayerTreeHostTestAddAnimation : public CCLayerTreeHostTestThreadOnly { +public: + CCLayerTreeHostTestAddAnimation() + : m_numAnimates(0) + , m_layerTreeHostImpl(0) + { + } + + virtual void beginTest() + { + postAddAnimationToMainThread(); + } + + virtual void animateLayers(CCLayerTreeHostImpl* layerTreeHostImpl) + { + if (!m_numAnimates) { + // The animation had zero duration so layerTreeHostImpl should no + // longer need to animate its layers. + EXPECT_FALSE(layerTreeHostImpl->needsAnimateLayers()); + m_numAnimates++; + return; + } + endTest(); + } + + virtual void afterTest() + { + } + +private: + int m_numAnimates; + CCLayerTreeHostImpl* m_layerTreeHostImpl; +}; + +TEST_F(CCLayerTreeHostTestAddAnimation, runMultiThread) +{ + runTestThreaded(); +} + class CCLayerTreeHostTestScrollSimple : public CCLayerTreeHostTestThreadOnly { public: CCLayerTreeHostTestScrollSimple() @@ -938,6 +1011,75 @@ TEST_F(CCLayerTreeHostTestScrollMultipleRedraw, DISABLED_runMultiThread) runTestThreaded(); } +// Verifies that startPageScaleAnimation events propagate correctly from CCLayerTreeHost to +// CCLayerTreeHostImpl in the MT compositor. +class CCLayerTreeHostTestStartPageScaleAnimation : public CCLayerTreeHostTest { +public: + + CCLayerTreeHostTestStartPageScaleAnimation() + : m_animationRequested(false) + { + } + + virtual void beginTest() + { + m_layerTreeHost->rootLayer()->setScrollable(true); + m_layerTreeHost->rootLayer()->setScrollPosition(IntPoint()); + postSetNeedsRedrawToMainThread(); + } + + static void requestStartPageScaleAnimation(void* self) + { + CCLayerTreeHostTestStartPageScaleAnimation* test = static_cast<CCLayerTreeHostTestStartPageScaleAnimation*>(self); + if (test->layerTreeHost()) + test->layerTreeHost()->startPageScaleAnimation(IntSize(), false, 1.25, 0); + } + + virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl) + { + impl->rootLayer()->setScrollable(true); + impl->rootLayer()->setScrollPosition(IntPoint()); + impl->setPageScaleFactorAndLimits(impl->pageScale(), 0.5, 2); + + // We request animation only once. + if (!m_animationRequested) { + callOnMainThread(CCLayerTreeHostTestStartPageScaleAnimation::requestStartPageScaleAnimation, this); + m_animationRequested = true; + } + } + + virtual void applyScrollAndScale(const IntSize& scrollDelta, float scale) + { + IntPoint position = m_layerTreeHost->rootLayer()->scrollPosition(); + m_layerTreeHost->rootLayer()->setScrollPosition(position + scrollDelta); + m_layerTreeHost->setPageScaleFactorAndLimits(scale, 0.5, 2); + } + + virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl* impl) + { + impl->processScrollDeltas(); + // We get one commit before the first draw, and the animation doesn't happen until the second draw, + // so results available on the third commit. + if (impl->frameNumber() == 2) { + EXPECT_EQ(1.25, impl->pageScale()); + endTest(); + } else + postSetNeedsRedrawToMainThread(); + } + + virtual void afterTest() + { + } + +private: + bool m_animationRequested; +}; + +TEST_F(CCLayerTreeHostTestStartPageScaleAnimation, runTest) +{ + runTest(true); +} + class CCLayerTreeHostTestSetVisible : public CCLayerTreeHostTest { public: @@ -1596,6 +1738,94 @@ public: SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestLayerOcclusion) +class CCLayerTreeHostTestLayerOcclusionWithFilters : public CCLayerTreeHostTest { +public: + CCLayerTreeHostTestLayerOcclusionWithFilters() { } + + virtual void beginTest() + { + RefPtr<TestLayerChromium> rootLayer = TestLayerChromium::create(); + RefPtr<TestLayerChromium> child = TestLayerChromium::create(); + RefPtr<TestLayerChromium> child2 = TestLayerChromium::create(); + RefPtr<TestLayerChromium> grandChild = TestLayerChromium::create(); + RefPtr<TestLayerChromium> mask = TestLayerChromium::create(); + + TransformationMatrix identityMatrix; + TransformationMatrix childTransform; + childTransform.translate(250, 250); + childTransform.rotate(90); + childTransform.translate(-250, -250); + + child->setMasksToBounds(true); + + // If the child layer has a filter that changes alpha values, and is below child2, then child2 should contribute to occlusion on everything, + // and child shouldn't contribute to the rootLayer + setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true); + setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true); + setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true); + setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true); + + { + FilterOperations filters; + filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::OPACITY)); + child->setFilters(filters); + } + + m_layerTreeHost->setRootLayer(rootLayer); + m_layerTreeHost->setViewportSize(rootLayer->bounds()); + m_layerTreeHost->updateLayers(); + m_layerTreeHost->commitComplete(); + + EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds()); + EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), grandChild->occludedScreenSpace().bounds()); + EXPECT_EQ(1u, grandChild->occludedScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(10, 40, 90, 60), child->occludedScreenSpace().bounds()); + EXPECT_EQ(2u, child->occludedScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds()); + EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size()); + + // If the child layer has a filter that moves pixels/changes alpha, and is below child2, then child should not inherit occlusion from outside its subtree, + // and should not contribute to the rootLayer + setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true); + setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true); + setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true); + setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true); + + { + FilterOperations filters; + filters.operations().append(BlurFilterOperation::create(Length(10, WebCore::Percent), FilterOperation::BLUR)); + child->setFilters(filters); + } + + m_layerTreeHost->setRootLayer(rootLayer); + m_layerTreeHost->setViewportSize(rootLayer->bounds()); + m_layerTreeHost->updateLayers(); + m_layerTreeHost->commitComplete(); + + EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds()); + EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds()); + EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds()); + EXPECT_EQ(1u, child->occludedScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds()); + EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size()); + + // Kill the layerTreeHost immediately. + m_layerTreeHost->setRootLayer(0); + m_layerTreeHost.clear(); + + endTest(); + } + + virtual void afterTest() + { + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestLayerOcclusionWithFilters) + class CCLayerTreeHostTestManySurfaces : public CCLayerTreeHostTest { public: CCLayerTreeHostTestManySurfaces() { } diff --git a/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp b/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp new file mode 100644 index 000000000..678ec9645 --- /dev/null +++ b/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp @@ -0,0 +1,1173 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "cc/CCOcclusionTracker.h" + +#include "FilterOperations.h" +#include "LayerChromium.h" +#include "Region.h" +#include "TransformationMatrix.h" +#include "cc/CCLayerTreeHostCommon.h" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +using namespace WebCore; + +#define EXPECT_EQ_RECT(a, b) \ + EXPECT_EQ(a.x(), b.x()); \ + EXPECT_EQ(a.y(), b.y()); \ + EXPECT_EQ(a.width(), b.width()); \ + EXPECT_EQ(a.height(), b.height()); + +namespace { + +void setLayerPropertiesForTesting(LayerChromium* layer, const TransformationMatrix& transform, const TransformationMatrix& sublayerTransform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool opaque) +{ + layer->setTransform(transform); + layer->setSublayerTransform(sublayerTransform); + layer->setAnchorPoint(anchor); + layer->setPosition(position); + layer->setBounds(bounds); + layer->setOpaque(opaque); +} + +class LayerChromiumWithForcedDrawsContent : public LayerChromium { +public: + LayerChromiumWithForcedDrawsContent() + : LayerChromium() + { + } + + virtual bool drawsContent() const { return true; } +}; + +// A subclass to expose the total current occlusion. +class TestCCOcclusionTracker : public CCOcclusionTracker { +public: + Region occlusionInScreenSpace() const { return CCOcclusionTracker::m_stack.last().occlusionInScreen; } + Region occlusionInTargetSurface() const { return CCOcclusionTracker::m_stack.last().occlusionInTarget; } + + void setOcclusionInScreenSpace(const Region& region) { CCOcclusionTracker::m_stack.last().occlusionInScreen = region; } + void setOcclusionInTargetSurface(const Region& region) { CCOcclusionTracker::m_stack.last().occlusionInTarget = region; } +}; + +TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegion) +{ + // This tests that the right transforms are being used. + TestCCOcclusionTracker occlusion; + const TransformationMatrix identityMatrix; + RefPtr<LayerChromium> parent = LayerChromium::create(); + RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent()); + parent->createRenderSurface(); + parent->addChild(layer); + + setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); + setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true); + + Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; + Vector<RefPtr<LayerChromium> > dummyLayerList; + int dummyMaxTextureSize = 512; + + parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); + parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); + renderSurfaceLayerList.append(parent); + + CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); + + occlusion.enterTargetRenderSurface(parent->renderSurface()); + occlusion.markOccludedBehindLayer(layer.get()); + EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 30, 70, 70))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 31, 70, 70))); + + EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 70, 70)).isEmpty()); + EXPECT_EQ_RECT(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 30, 70, 70))); + EXPECT_EQ_RECT(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 29, 70, 70))); + EXPECT_EQ_RECT(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 70, 70))); + EXPECT_EQ_RECT(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 29, 70, 70))); + EXPECT_EQ_RECT(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 30, 70, 70))); + EXPECT_EQ_RECT(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 31, 70, 70))); + EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 31, 70, 70))); + EXPECT_EQ_RECT(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 31, 70, 70))); +} + +TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegionWithRotation) +{ + // This tests that the right transforms are being used. + TestCCOcclusionTracker occlusion; + const TransformationMatrix identityMatrix; + RefPtr<LayerChromium> parent = LayerChromium::create(); + RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent()); + parent->createRenderSurface(); + parent->addChild(layer); + + TransformationMatrix layerTransform; + layerTransform.translate(250, 250); + layerTransform.rotate(90); + layerTransform.translate(-250, -250); + + setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); + setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true); + + Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; + Vector<RefPtr<LayerChromium> > dummyLayerList; + int dummyMaxTextureSize = 512; + + parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); + parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); + renderSurfaceLayerList.append(parent); + + CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); + + occlusion.enterTargetRenderSurface(parent->renderSurface()); + occlusion.markOccludedBehindLayer(layer.get()); + EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 30, 70, 70))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 31, 70, 70))); + + EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 70, 70)).isEmpty()); + EXPECT_EQ_RECT(IntRect(29, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 30, 70, 70))); + EXPECT_EQ_RECT(IntRect(29, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 29, 70, 70))); + EXPECT_EQ_RECT(IntRect(30, 29, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 70, 70))); + EXPECT_EQ_RECT(IntRect(31, 29, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 29, 70, 70))); + EXPECT_EQ_RECT(IntRect(100, 30, 1, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 30, 70, 70))); + EXPECT_EQ_RECT(IntRect(31, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 31, 70, 70))); + EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 31, 70, 70))); + EXPECT_EQ_RECT(IntRect(29, 31, 70, 70), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 31, 70, 70))); +} + +TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegionWithTranslation) +{ + // This tests that the right transforms are being used. + TestCCOcclusionTracker occlusion; + const TransformationMatrix identityMatrix; + RefPtr<LayerChromium> parent = LayerChromium::create(); + RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent()); + parent->createRenderSurface(); + parent->addChild(layer); + + TransformationMatrix layerTransform; + layerTransform.translate(20, 20); + + setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); + setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true); + + Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; + Vector<RefPtr<LayerChromium> > dummyLayerList; + int dummyMaxTextureSize = 512; + + parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); + parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); + renderSurfaceLayerList.append(parent); + + CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); + + occlusion.enterTargetRenderSurface(parent->renderSurface()); + occlusion.markOccludedBehindLayer(layer.get()); + EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(50, 50, 50, 50))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(49, 50, 50, 50))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(50, 49, 50, 50))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(51, 50, 50, 50))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(50, 51, 50, 50))); + + EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(50, 50, 50, 50)).isEmpty()); + EXPECT_EQ_RECT(IntRect(49, 50, 1, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 50, 50, 50))); + EXPECT_EQ_RECT(IntRect(49, 49, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 49, 50, 50))); + EXPECT_EQ_RECT(IntRect(50, 49, 50, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(50, 49, 50, 50))); + EXPECT_EQ_RECT(IntRect(51, 49, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 49, 50, 50))); + EXPECT_EQ_RECT(IntRect(100, 50, 1, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 50, 50, 50))); + EXPECT_EQ_RECT(IntRect(51, 51, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(51, 51, 50, 50))); + EXPECT_EQ_RECT(IntRect(50, 100, 50, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(50, 51, 50, 50))); + EXPECT_EQ_RECT(IntRect(49, 51, 50, 50), occlusion.unoccludedContentRect(parent.get(), IntRect(49, 51, 50, 50))); +} + +TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegionWithRotatedSurface) +{ + // This tests that the right transforms are being used. + TestCCOcclusionTracker occlusion; + const TransformationMatrix identityMatrix; + RefPtr<LayerChromium> parent = LayerChromium::create(); + RefPtr<LayerChromium> child = LayerChromium::create(); + RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent()); + parent->createRenderSurface(); + parent->addChild(child); + child->addChild(layer); + + TransformationMatrix childTransform; + childTransform.translate(250, 250); + childTransform.rotate(90); + childTransform.translate(-250, -250); + + setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); + setLayerPropertiesForTesting(child.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false); + setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true); + + child->setMasksToBounds(true); + + Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; + Vector<RefPtr<LayerChromium> > dummyLayerList; + int dummyMaxTextureSize = 512; + + parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); + parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); + renderSurfaceLayerList.append(parent); + + CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); + + occlusion.enterTargetRenderSurface(child->renderSurface()); + occlusion.markOccludedBehindLayer(layer.get()); + + EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70))); + EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70))); + EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70))); + EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 430, 61, 70))); + EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 71))); + + occlusion.markOccludedBehindLayer(child.get()); + occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface()); + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + + EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60))); + + + /* Justification for the above occlusion from |layer|: + 100 + +---------------------+ +---------------------+ + | | | |30 Visible region of |layer|: ///// + | 30 | rotate(90) | | + | 30 + ---------------------------------+ | +---------------------------------+ + 100 | | 10 | | ==> | | |10 | + | |10+---------------------------------+ | +---------------------------------+ | + | | | | | | | | |///////////////| 420 | | + | | | | | | | | |///////////////|60 | | + | | | | | | | | |///////////////| | | + +----|--|-------------+ | | +--|--|---------------+ | | + | | | | 20|10| 70 | | + | | | | | | | | + | | | |500 | | | | + | | | | | | | | + | | | | | | | | + | | | | | | | | + | | | | | | |10| + +--|-------------------------------+ | | +------------------------------|--+ + | | | 490 | + +---------------------------------+ +---------------------------------+ + 500 500 + */ +} + +TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegionWithSurfaceAlreadyOnStack) +{ + // This tests that the right transforms are being used. + TestCCOcclusionTracker occlusion; + const TransformationMatrix identityMatrix; + RefPtr<LayerChromium> parent = LayerChromium::create(); + RefPtr<LayerChromium> child = LayerChromium::create(); + RefPtr<LayerChromiumWithForcedDrawsContent> child2 = adoptRef(new LayerChromiumWithForcedDrawsContent()); + RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent()); + parent->createRenderSurface(); + parent->addChild(child); + child->addChild(layer); + parent->addChild(child2); + + TransformationMatrix childTransform; + childTransform.translate(250, 250); + childTransform.rotate(90); + childTransform.translate(-250, -250); + + setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); + setLayerPropertiesForTesting(child.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false); + setLayerPropertiesForTesting(layer.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true); + + // |child2| makes |parent|'s surface get considered by CCOcclusionTracker first, instead of |child|'s. This exercises different code in + // leaveToTargetRenderSurface, as the target surface has already been seen. + setLayerPropertiesForTesting(child2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(60, 20), true); + + child->setMasksToBounds(true); + + Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; + Vector<RefPtr<LayerChromium> > dummyLayerList; + int dummyMaxTextureSize = 512; + + parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); + parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); + renderSurfaceLayerList.append(parent); + + CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); + + occlusion.enterTargetRenderSurface(parent->renderSurface()); + occlusion.markOccludedBehindLayer(child2.get()); + + EXPECT_EQ_RECT(IntRect(30, 30, 60, 20), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(30, 30, 60, 20), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + occlusion.enterTargetRenderSurface(child->renderSurface()); + occlusion.markOccludedBehindLayer(layer.get()); + + EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70))); + EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70))); + EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70))); + EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(11, 430, 60, 70))); + EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 431, 60, 70))); + + EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 430, 60, 70)).isEmpty()); + // This is the little piece not occluded by child2 + EXPECT_EQ_RECT(IntRect(9, 430, 1, 10), occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 70))); + // This extends past both sides of child2, so it will be the original rect. + EXPECT_EQ_RECT(IntRect(9, 430, 60, 80), occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 80))); + // This extends past two adjacent sides of child2, and should included the unoccluded parts of each side. + // This also demonstrates that the rect can be arbitrary and does not get clipped to the layer's visibleLayerRect(). + EXPECT_EQ_RECT(IntRect(-10, 430, 20, 70), occlusion.unoccludedContentRect(child.get(), IntRect(-10, 430, 60, 70))); + // This extends past three adjacent sides of child2, so it should contain the unoccluded parts of each side. The left + // and bottom edges are completely unoccluded for some row/column so we get back the original query rect. + EXPECT_EQ_RECT(IntRect(-10, 430, 60, 80), occlusion.unoccludedContentRect(child.get(), IntRect(-10, 430, 60, 80))); + EXPECT_EQ_RECT(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 429, 60, 70))); + EXPECT_EQ_RECT(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child.get(), IntRect(11, 430, 60, 70))); + EXPECT_EQ_RECT(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 431, 60, 70))); + + // Surface is not occluded by things that draw into itself. + EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.surfaceUnoccludedContentRect(child.get(), IntRect(10, 430, 60, 70))); + + occlusion.markOccludedBehindLayer(child.get()); + // |child2| should get merged with the surface we are leaving now + occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface()); + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + + EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size()); + + Vector<IntRect> screen = occlusion.occlusionInScreenSpace().rects(); + Vector<IntRect> target = occlusion.occlusionInTargetSurface().rects(); + + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70))); + EXPECT_EQ_RECT(IntRect(90, 30, 10, 10), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 70, 70))); + + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 60, 10))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 60, 10))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 60, 10))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(31, 30, 60, 10))); + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 31, 60, 10))); + + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60))); + + EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 30, 60, 10)).isEmpty()); + EXPECT_EQ_RECT(IntRect(29, 30, 1, 10), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 30, 60, 10))); + EXPECT_EQ_RECT(IntRect(30, 29, 60, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 60, 10))); + EXPECT_EQ_RECT(IntRect(90, 30, 1, 10), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 30, 60, 10))); + EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 31, 60, 10)).isEmpty()); + + EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 40, 70, 60)).isEmpty()); + EXPECT_EQ_RECT(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 40, 70, 60))); + // This rect is mostly occluded by |child2|. + EXPECT_EQ_RECT(IntRect(90, 39, 10, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 39, 70, 60))); + // This rect extends past top/right ends of |child2|. + EXPECT_EQ_RECT(IntRect(30, 29, 70, 11), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 29, 70, 70))); + // This rect extends past left/right ends of |child2|. + EXPECT_EQ_RECT(IntRect(20, 39, 80, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(20, 39, 80, 60))); + EXPECT_EQ_RECT(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 40, 70, 60))); + EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 41, 70, 60))); + + // Surface is not occluded by things that draw into itself. + EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.surfaceUnoccludedContentRect(parent.get(), IntRect(30, 40, 70, 60))); + + + /* Justification for the above occlusion from |layer|: + 100 + +---------------------+ +---------------------+ + | | | |30 Visible region of |layer|: ///// + | 30 | rotate(90) | 30 60 | |child2|: \\\\\ + | 30 + ------------+--------------------+ | 30 +------------+--------------------+ + 100 | | 10 | | | ==> | |\\\\\\\\\\\\| |10 | + | |10+----------|----------------------+ | +--|\\\\\\\\\\\\|-----------------+ | + | + ------------+ | | | | | +------------+//| 420 | | + | | | | | | | | |///////////////|60 | | + | | | | | | | | |///////////////| | | + +----|--|-------------+ | | +--|--|---------------+ | | + | | | | 20|10| 70 | | + | | | | | | | | + | | | |500 | | | | + | | | | | | | | + | | | | | | | | + | | | | | | | | + | | | | | | |10| + +--|-------------------------------+ | | +------------------------------|--+ + | | | 490 | + +---------------------------------+ +---------------------------------+ + 500 500 + */ +} + +TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegionWithRotatedOffAxisSurface) +{ + TestCCOcclusionTracker occlusion; + const TransformationMatrix identityMatrix; + RefPtr<LayerChromium> parent = LayerChromium::create(); + RefPtr<LayerChromium> child = LayerChromium::create(); + RefPtr<LayerChromiumWithForcedDrawsContent> layer = adoptRef(new LayerChromiumWithForcedDrawsContent()); + parent->createRenderSurface(); + parent->addChild(child); + child->addChild(layer); + + // Now rotate the child a little more so it is not axis-aligned. The parent will no longer be occluded by |layer|, but + // the child's occlusion should be unchanged. + + TransformationMatrix childTransform; + childTransform.translate(250, 250); + childTransform.rotate(95); + childTransform.translate(-250, -250); + + TransformationMatrix layerTransform; + layerTransform.translate(10, 10); + + setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); + setLayerPropertiesForTesting(child.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false); + setLayerPropertiesForTesting(layer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), true); + + child->setMasksToBounds(true); + + Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; + Vector<RefPtr<LayerChromium> > dummyLayerList; + int dummyMaxTextureSize = 512; + + parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); + parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); + renderSurfaceLayerList.append(parent); + + CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); + + IntRect clippedLayerInChild = layerTransform.mapRect(layer->visibleLayerRect()); + + occlusion.enterTargetRenderSurface(child->renderSurface()); + occlusion.markOccludedBehindLayer(layer.get()); + + EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(clippedLayerInChild, occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(child.get(), clippedLayerInChild)); + EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty()); + clippedLayerInChild.move(-1, 0); + EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild)); + EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty()); + clippedLayerInChild.move(1, 0); + clippedLayerInChild.move(1, 0); + EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild)); + EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty()); + clippedLayerInChild.move(-1, 0); + clippedLayerInChild.move(0, -1); + EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild)); + EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty()); + clippedLayerInChild.move(0, 1); + clippedLayerInChild.move(0, 1); + EXPECT_FALSE(occlusion.occluded(child.get(), clippedLayerInChild)); + EXPECT_FALSE(occlusion.unoccludedContentRect(parent.get(), clippedLayerInChild).isEmpty()); + clippedLayerInChild.move(0, -1); + + // Surface is not occluded by things that draw into itself. + EXPECT_EQ_RECT(IntRect(0, 0, 500, 500), occlusion.surfaceUnoccludedContentRect(child.get(), IntRect(0, 0, 500, 500))); + + occlusion.markOccludedBehindLayer(child.get()); + occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface()); + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + + EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(75, 55, 1, 1))); + EXPECT_EQ_RECT(IntRect(75, 55, 1, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(75, 55, 1, 1))); + + // Surface is not occluded by things that draw into itself. + EXPECT_EQ_RECT(IntRect(0, 0, 100, 100), occlusion.surfaceUnoccludedContentRect(parent.get(), IntRect(0, 0, 100, 100))); +} + +TEST(CCOcclusionTrackerTest, layerAddedToOccludedRegionWithMultipleOpaqueLayers) +{ + // This is similar to the previous test but now we make a few opaque layers inside of |child| so that the occluded parts of child are not a simple rect. + TestCCOcclusionTracker occlusion; + const TransformationMatrix identityMatrix; + RefPtr<LayerChromium> parent = LayerChromium::create(); + RefPtr<LayerChromium> child = LayerChromium::create(); + RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent()); + RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent()); + parent->createRenderSurface(); + parent->addChild(child); + child->addChild(layer1); + child->addChild(layer2); + + TransformationMatrix childTransform; + childTransform.translate(250, 250); + childTransform.rotate(90); + childTransform.translate(-250, -250); + + setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); + setLayerPropertiesForTesting(child.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false); + setLayerPropertiesForTesting(layer1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 440), true); + setLayerPropertiesForTesting(layer2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(10, 450), IntSize(500, 60), true); + + child->setMasksToBounds(true); + + Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; + Vector<RefPtr<LayerChromium> > dummyLayerList; + int dummyMaxTextureSize = 512; + + parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); + parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); + renderSurfaceLayerList.append(parent); + + CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); + + occlusion.enterTargetRenderSurface(child->renderSurface()); + occlusion.markOccludedBehindLayer(layer2.get()); + occlusion.markOccludedBehindLayer(layer1.get()); + + EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(child.get(), IntRect(10, 430, 60, 70))); + EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(9, 430, 60, 70))); + EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 429, 60, 70))); + EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(11, 430, 60, 70))); + EXPECT_FALSE(occlusion.occluded(child.get(), IntRect(10, 431, 60, 70))); + + EXPECT_TRUE(occlusion.unoccludedContentRect(child.get(), IntRect(10, 430, 60, 70)).isEmpty()); + EXPECT_EQ_RECT(IntRect(9, 430, 1, 70), occlusion.unoccludedContentRect(child.get(), IntRect(9, 430, 60, 70))); + EXPECT_EQ_RECT(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 429, 60, 70))); + EXPECT_EQ_RECT(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child.get(), IntRect(11, 430, 60, 70))); + EXPECT_EQ_RECT(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child.get(), IntRect(10, 431, 60, 70))); + + // Surface is not occluded by things that draw into itself. + EXPECT_EQ_RECT(IntRect(10, 430, 60, 70), occlusion.surfaceUnoccludedContentRect(child.get(), IntRect(10, 430, 60, 70))); + + occlusion.markOccludedBehindLayer(child.get()); + occlusion.finishedTargetRenderSurface(child.get(), child->renderSurface()); + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + + EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 40, 70, 60))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 40, 70, 60))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 39, 70, 60))); + + EXPECT_TRUE(occlusion.unoccludedContentRect(parent.get(), IntRect(30, 40, 70, 60)).isEmpty()); + EXPECT_EQ_RECT(IntRect(29, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(29, 40, 70, 60))); + EXPECT_EQ_RECT(IntRect(30, 39, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 39, 70, 60))); + EXPECT_EQ_RECT(IntRect(100, 40, 1, 60), occlusion.unoccludedContentRect(parent.get(), IntRect(31, 40, 70, 60))); + EXPECT_EQ_RECT(IntRect(30, 100, 70, 1), occlusion.unoccludedContentRect(parent.get(), IntRect(30, 41, 70, 60))); + + // Surface is not occluded by things that draw into itself. + EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), occlusion.surfaceUnoccludedContentRect(parent.get(), IntRect(30, 40, 70, 60))); + + + /* Justification for the above occlusion from |layer1| and |layer2|: + + +---------------------+ + | |30 Visible region of |layer1|: ///// + | | Visible region of |layer2|: \\\\\ + | +---------------------------------+ + | | |10 | + | +---------------+-----------------+ | + | | |\\\\\\\\\\\\|//| 420 | | + | | |\\\\\\\\\\\\|//|60 | | + | | |\\\\\\\\\\\\|//| | | + +--|--|------------|--+ | | + 20|10| 70 | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | | | + | | | |10| + | +------------|-----------------|--+ + | | 490 | + +---------------+-----------------+ + 60 440 + */ +} + +TEST(CCOcclusionTrackerTest, surfaceOcclusionWithOverlappingSiblingSurfaces) +{ + // This tests that the right transforms are being used. + TestCCOcclusionTracker occlusion; + const TransformationMatrix identityMatrix; + RefPtr<LayerChromium> parent = LayerChromium::create(); + RefPtr<LayerChromium> child1 = LayerChromium::create(); + RefPtr<LayerChromium> child2 = LayerChromium::create(); + RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent()); + RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent()); + parent->createRenderSurface(); + parent->addChild(child1); + parent->addChild(child2); + child1->addChild(layer1); + child2->addChild(layer2); + + TransformationMatrix childTransform; + childTransform.translate(250, 250); + childTransform.rotate(90); + childTransform.translate(-250, -250); + + setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); + setLayerPropertiesForTesting(child1.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false); + setLayerPropertiesForTesting(layer1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), true); + setLayerPropertiesForTesting(child2.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(20, 40), IntSize(500, 500), false); + setLayerPropertiesForTesting(layer2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), true); + + child1->setMasksToBounds(true); + child2->setMasksToBounds(true); + + Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; + Vector<RefPtr<LayerChromium> > dummyLayerList; + int dummyMaxTextureSize = 512; + + parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); + parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); + renderSurfaceLayerList.append(parent); + + CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); + + occlusion.enterTargetRenderSurface(child2->renderSurface()); + occlusion.markOccludedBehindLayer(layer2.get()); + + EXPECT_EQ_RECT(IntRect(20, 40, 80, 60), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(0, 420, 60, 80), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(0, 420, 60, 80))); + EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-1, 420, 60, 80))); + EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(0, 419, 60, 80))); + EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(0, 420, 61, 80))); + EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(0, 420, 60, 81))); + + // Surface is not occluded by things that draw into itself. + EXPECT_EQ_RECT(IntRect(0, 420, 60, 80), occlusion.surfaceUnoccludedContentRect(child2.get(), IntRect(0, 420, 60, 80))); + + occlusion.markOccludedBehindLayer(child2.get()); + occlusion.finishedTargetRenderSurface(child2.get(), child2->renderSurface()); + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + occlusion.enterTargetRenderSurface(child1->renderSurface()); + occlusion.markOccludedBehindLayer(layer1.get()); + + EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(0, 430, 70, 70), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(child1.get(), IntRect(0, 430, 70, 70))); + EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-1, 430, 70, 70))); + EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(0, 429, 70, 70))); + EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(0, 430, 71, 70))); + EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(0, 430, 70, 71))); + + // Surface is not occluded by things that draw into itself, but the |child1| surface should be occluded by the |child2| surface. + EXPECT_EQ_RECT(IntRect(0, 430, 10, 70), occlusion.surfaceUnoccludedContentRect(child1.get(), IntRect(0, 430, 70, 70))); + + occlusion.markOccludedBehindLayer(child1.get()); + occlusion.finishedTargetRenderSurface(child1.get(), child1->renderSurface()); + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + + EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 30, 80, 70))); + + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 30, 70, 70))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 30, 70, 70))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 29, 70, 70))); + + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(20, 40, 80, 60))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(19, 40, 80, 60))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 39, 80, 60))); + + // |child1| and |child2| both draw into parent so they should not occlude it. + EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.surfaceUnoccludedContentRect(parent.get(), IntRect(20, 30, 80, 70))); + + + /* Justification for the above occlusion: + 100 + +---------------------+ + | | + | 30 | child1 + | 30+ ---------------------------------+ + 100 | 40| | child2 | + |20+----------------------------------+ | + | | | | | | + | | | | | | + | | | | | | + +--|-|----------------+ | | + | | | | 500 + | | | | + | | | | + | | | | + | | | | + | | | | + | | | | + | +--------------------------------|-+ + | | + +----------------------------------+ + 500 + */ +} + +TEST(CCOcclusionTrackerTest, surfaceOcclusionInScreenSpace) +{ + // This tests that the right transforms are being used. + TestCCOcclusionTracker occlusion; + const TransformationMatrix identityMatrix; + RefPtr<LayerChromium> parent = LayerChromium::create(); + RefPtr<LayerChromium> child1 = LayerChromium::create(); + RefPtr<LayerChromium> child2 = LayerChromium::create(); + RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent()); + RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent()); + parent->createRenderSurface(); + parent->addChild(child1); + parent->addChild(child2); + child1->addChild(layer1); + child2->addChild(layer2); + + TransformationMatrix childTransform; + childTransform.translate(250, 250); + childTransform.rotate(90); + childTransform.translate(-250, -250); + + // The owning layers have very different bounds from the surfaces that they own. + setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); + setLayerPropertiesForTesting(child1.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(10, 10), false); + setLayerPropertiesForTesting(layer1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(-10, -10), IntSize(510, 510), true); + setLayerPropertiesForTesting(child2.get(), childTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(20, 40), IntSize(10, 10), false); + setLayerPropertiesForTesting(layer2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(-10, -10), IntSize(510, 510), true); + + // Make them both render surfaces + FilterOperations filters; + filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE)); + child1->setFilters(filters); + child2->setFilters(filters); + + child1->setMasksToBounds(false); + child2->setMasksToBounds(false); + + Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; + Vector<RefPtr<LayerChromium> > dummyLayerList; + int dummyMaxTextureSize = 512; + + parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); + parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); + renderSurfaceLayerList.append(parent); + + CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); + + occlusion.enterTargetRenderSurface(child2->renderSurface()); + occlusion.markOccludedBehindLayer(layer2.get()); + + EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 80))); + EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-11, 420, 70, 80))); + EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 419, 70, 80))); + EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 71, 80))); + EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 81))); + + // Surface is not occluded by things that draw into itself. + EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.surfaceUnoccludedContentRect(child2.get(), IntRect(-10, 420, 70, 80))); + EXPECT_FALSE(occlusion.surfaceOccluded(child2.get(), IntRect(30, 250, 1, 1))); + + occlusion.markOccludedBehindLayer(child2.get()); + occlusion.finishedTargetRenderSurface(child2.get(), child2->renderSurface()); + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + occlusion.enterTargetRenderSurface(child1->renderSurface()); + occlusion.markOccludedBehindLayer(layer1.get()); + + EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(-10, 430, 80, 70), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(child1.get(), IntRect(-10, 430, 80, 70))); + EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-11, 430, 80, 70))); + EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-10, 429, 80, 70))); + EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-10, 430, 81, 70))); + EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(-10, 430, 80, 71))); + + // Surface is not occluded by things that draw into itself, but the |child1| surface should be occluded by the |child2| surface. + EXPECT_EQ_RECT(IntRect(-10, 430, 10, 80), occlusion.surfaceUnoccludedContentRect(child1.get(), IntRect(-10, 430, 70, 80))); + EXPECT_TRUE(occlusion.surfaceOccluded(child1.get(), IntRect(0, 430, 70, 80))); + EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(-1, 430, 70, 80))); + EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(0, 429, 70, 80))); + EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(1, 430, 70, 80))); + EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(0, 431, 70, 80))); + + occlusion.markOccludedBehindLayer(child1.get()); + occlusion.finishedTargetRenderSurface(child1.get(), child1->renderSurface()); + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + + EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(2u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 20, 80, 80))); + + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(30, 20, 70, 80))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(29, 20, 70, 80))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(30, 19, 70, 80))); + + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(20, 30, 80, 70))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(19, 30, 80, 70))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(20, 29, 80, 70))); + + // |child1| and |child2| both draw into parent so they should not occlude it. + EXPECT_EQ_RECT(IntRect(20, 20, 80, 80), occlusion.surfaceUnoccludedContentRect(parent.get(), IntRect(20, 20, 80, 80))); + EXPECT_FALSE(occlusion.surfaceOccluded(parent.get(), IntRect(50, 50, 1, 1))); + + + /* Justification for the above occlusion: + 100 + +---------------------+ + | 20 | layer1 + | 30+ ---------------------------------+ + 100 | 30| | layer2 | + |20+----------------------------------+ | + | | | | | | + | | | | | | + | | | | | | + +--|-|----------------+ | | + | | | | 510 + | | | | + | | | | + | | | | + | | | | + | | | | + | | | | + | +--------------------------------|-+ + | | + +----------------------------------+ + 510 + */ +} + +TEST(CCOcclusionTrackerTest, surfaceOcclusionInScreenSpaceDifferentTransforms) +{ + // This tests that the right transforms are being used. + TestCCOcclusionTracker occlusion; + const TransformationMatrix identityMatrix; + RefPtr<LayerChromium> parent = LayerChromium::create(); + RefPtr<LayerChromium> child1 = LayerChromium::create(); + RefPtr<LayerChromium> child2 = LayerChromium::create(); + RefPtr<LayerChromiumWithForcedDrawsContent> layer1 = adoptRef(new LayerChromiumWithForcedDrawsContent()); + RefPtr<LayerChromiumWithForcedDrawsContent> layer2 = adoptRef(new LayerChromiumWithForcedDrawsContent()); + parent->createRenderSurface(); + parent->addChild(child1); + parent->addChild(child2); + child1->addChild(layer1); + child2->addChild(layer2); + + TransformationMatrix child1Transform; + child1Transform.translate(250, 250); + child1Transform.rotate(-90); + child1Transform.translate(-250, -250); + + TransformationMatrix child2Transform; + child2Transform.translate(250, 250); + child2Transform.rotate(90); + child2Transform.translate(-250, -250); + + // The owning layers have very different bounds from the surfaces that they own. + setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); + setLayerPropertiesForTesting(child1.get(), child1Transform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 20), IntSize(10, 10), false); + setLayerPropertiesForTesting(layer1.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(-10, -20), IntSize(510, 520), true); + setLayerPropertiesForTesting(child2.get(), child2Transform, identityMatrix, FloatPoint(0, 0), FloatPoint(20, 40), IntSize(10, 10), false); + setLayerPropertiesForTesting(layer2.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(-10, -10), IntSize(510, 510), true); + + // Make them both render surfaces + FilterOperations filters; + filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE)); + child1->setFilters(filters); + child2->setFilters(filters); + + child1->setMasksToBounds(false); + child2->setMasksToBounds(false); + + Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; + Vector<RefPtr<LayerChromium> > dummyLayerList; + int dummyMaxTextureSize = 512; + + parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); + parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); + renderSurfaceLayerList.append(parent); + + CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); + + occlusion.enterTargetRenderSurface(child2->renderSurface()); + occlusion.markOccludedBehindLayer(layer2.get()); + + EXPECT_EQ_RECT(IntRect(20, 30, 80, 70), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 80))); + EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-11, 420, 70, 80))); + EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 419, 70, 80))); + EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 71, 80))); + EXPECT_FALSE(occlusion.occluded(child2.get(), IntRect(-10, 420, 70, 81))); + + // Surface is not occluded by things that draw into itself. + EXPECT_EQ_RECT(IntRect(-10, 420, 70, 80), occlusion.surfaceUnoccludedContentRect(child2.get(), IntRect(-10, 420, 70, 80))); + EXPECT_FALSE(occlusion.surfaceOccluded(child2.get(), IntRect(30, 250, 1, 1))); + + occlusion.markOccludedBehindLayer(child2.get()); + occlusion.finishedTargetRenderSurface(child2.get(), child2->renderSurface()); + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + occlusion.enterTargetRenderSurface(child1->renderSurface()); + occlusion.markOccludedBehindLayer(layer1.get()); + + EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(420, -20, 80, 90), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(child1.get(), IntRect(420, -20, 80, 90))); + EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(419, -20, 80, 90))); + EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(420, -21, 80, 90))); + EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(420, -19, 80, 90))); + EXPECT_FALSE(occlusion.occluded(child1.get(), IntRect(421, -20, 80, 90))); + + // Surface is not occluded by things that draw into itself, but the |child1| surface should be occluded by the |child2| surface. + EXPECT_EQ_RECT(IntRect(420, -20, 80, 90), occlusion.surfaceUnoccludedContentRect(child1.get(), IntRect(420, -20, 80, 90))); + EXPECT_EQ_RECT(IntRect(490, -10, 10, 80), occlusion.surfaceUnoccludedContentRect(child1.get(), IntRect(420, -10, 80, 80))); + EXPECT_EQ_RECT(IntRect(420, -20, 70, 10), occlusion.surfaceUnoccludedContentRect(child1.get(), IntRect(420, -20, 70, 90))); + EXPECT_TRUE(occlusion.surfaceOccluded(child1.get(), IntRect(420, -10, 70, 80))); + EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(419, -10, 70, 80))); + EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(420, -11, 70, 80))); + EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(421, -10, 70, 80))); + EXPECT_FALSE(occlusion.surfaceOccluded(child1.get(), IntRect(420, -9, 70, 80))); + + occlusion.markOccludedBehindLayer(child1.get()); + occlusion.finishedTargetRenderSurface(child1.get(), child1->renderSurface()); + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + + EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + EXPECT_TRUE(occlusion.occluded(parent.get(), IntRect(10, 20, 90, 80))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(9, 20, 90, 80))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(10, 19, 90, 80))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(11, 20, 90, 80))); + EXPECT_FALSE(occlusion.occluded(parent.get(), IntRect(10, 21, 90, 80))); + + // |child1| and |child2| both draw into parent so they should not occlude it. + EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), occlusion.surfaceUnoccludedContentRect(parent.get(), IntRect(10, 20, 90, 80))); + EXPECT_FALSE(occlusion.surfaceOccluded(parent.get(), IntRect(10, 20, 1, 1))); + EXPECT_FALSE(occlusion.surfaceOccluded(parent.get(), IntRect(99, 20, 1, 1))); + EXPECT_FALSE(occlusion.surfaceOccluded(parent.get(), IntRect(10, 9, 1, 1))); + EXPECT_FALSE(occlusion.surfaceOccluded(parent.get(), IntRect(99, 99, 1, 1))); + + + /* Justification for the above occlusion: + 100 + +---------------------+ + |20 | layer1 + 10+----------------------------------+ + 100 || 30 | layer2 | + |20+----------------------------------+ + || | | | | + || | | | | + || | | | | + +|-|------------------+ | | + | | | | 510 + | | 510 | | + | | | | + | | | | + | | | | + | | | | + | | 520 | | + +----------------------------------+ | + | | + +----------------------------------+ + 510 + */ +} + +TEST(CCOcclusionTrackerTest, occlusionInteractionWithFilters) +{ + // This tests that the right transforms are being used. + TestCCOcclusionTracker occlusion; + const TransformationMatrix identityMatrix; + RefPtr<LayerChromium> parent = LayerChromium::create(); + RefPtr<LayerChromiumWithForcedDrawsContent> blurLayer = adoptRef(new LayerChromiumWithForcedDrawsContent()); + RefPtr<LayerChromiumWithForcedDrawsContent> opacityLayer = adoptRef(new LayerChromiumWithForcedDrawsContent()); + RefPtr<LayerChromiumWithForcedDrawsContent> opaqueLayer = adoptRef(new LayerChromiumWithForcedDrawsContent()); + parent->createRenderSurface(); + parent->addChild(blurLayer); + parent->addChild(opacityLayer); + parent->addChild(opaqueLayer); + + TransformationMatrix layerTransform; + layerTransform.translate(250, 250); + layerTransform.rotate(90); + layerTransform.translate(-250, -250); + + setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), false); + setLayerPropertiesForTesting(blurLayer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true); + setLayerPropertiesForTesting(opaqueLayer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true); + setLayerPropertiesForTesting(opacityLayer.get(), layerTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true); + + { + FilterOperations filters; + filters.operations().append(BlurFilterOperation::create(Length(10, WebCore::Percent), FilterOperation::BLUR)); + blurLayer->setFilters(filters); + } + + { + FilterOperations filters; + filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::GRAYSCALE)); + opaqueLayer->setFilters(filters); + } + + { + FilterOperations filters; + filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::OPACITY)); + opacityLayer->setFilters(filters); + } + + + Vector<RefPtr<LayerChromium> > renderSurfaceLayerList; + Vector<RefPtr<LayerChromium> > dummyLayerList; + int dummyMaxTextureSize = 512; + + parent->renderSurface()->setContentRect(IntRect(IntPoint::zero(), parent->bounds())); + parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds())); + renderSurfaceLayerList.append(parent); + + CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(parent.get(), parent.get(), identityMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize); + + // Opacity layer won't contribute to occlusion. + occlusion.enterTargetRenderSurface(opacityLayer->renderSurface()); + occlusion.markOccludedBehindLayer(opacityLayer.get()); + occlusion.finishedTargetRenderSurface(opacityLayer.get(), opacityLayer->renderSurface()); + + EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty()); + EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty()); + + // And has nothing to contribute to its parent surface. + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty()); + EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty()); + + // Opaque layer will contribute to occlusion. + occlusion.enterTargetRenderSurface(opaqueLayer->renderSurface()); + occlusion.markOccludedBehindLayer(opaqueLayer.get()); + occlusion.finishedTargetRenderSurface(opaqueLayer.get(), opaqueLayer->renderSurface()); + + EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(0, 430, 70, 70), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + // And it gets translated to the parent surface. + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); + + // The blur layer needs to throw away any occlusion from outside its subtree. + occlusion.enterTargetRenderSurface(blurLayer->renderSurface()); + EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty()); + EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty()); + + // And it won't contribute to occlusion. + occlusion.markOccludedBehindLayer(blurLayer.get()); + occlusion.finishedTargetRenderSurface(blurLayer.get(), blurLayer->renderSurface()); + EXPECT_TRUE(occlusion.occlusionInScreenSpace().isEmpty()); + EXPECT_TRUE(occlusion.occlusionInTargetSurface().isEmpty()); + + // But the opaque layer's occlusion is preserved on the parent. + occlusion.leaveToTargetRenderSurface(parent->renderSurface()); + EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); + EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); +} + +} // namespace diff --git a/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp b/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp index 299e5c7e5..d49703e14 100644 --- a/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp +++ b/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp @@ -79,7 +79,7 @@ TEST(CCQuadCullerTest, verifyCullChildLinesUpTopLeft) setQuads(rootState.get(), childState.get(), quadList); EXPECT_EQ(quadList.size(), 13u); - CCQuadCuller::cullOccludedQuads(quadList); + CCQuadCuller::cullOccludedQuads(quadList, false, IntRect()); EXPECT_EQ(quadList.size(), 9u); } @@ -92,7 +92,7 @@ TEST(CCQuadCullerTest, verifyCullWhenChildOpacityNotOne) setQuads(rootState.get(), childState.get(), quadList); EXPECT_EQ(quadList.size(), 13u); - CCQuadCuller::cullOccludedQuads(quadList); + CCQuadCuller::cullOccludedQuads(quadList, false, IntRect()); EXPECT_EQ(quadList.size(), 13u); } @@ -105,7 +105,7 @@ TEST(CCQuadCullerTest, verifyCullWhenChildOpaqueFlagFalse) setQuads(rootState.get(), childState.get(), quadList); EXPECT_EQ(quadList.size(), 13u); - CCQuadCuller::cullOccludedQuads(quadList); + CCQuadCuller::cullOccludedQuads(quadList, false, IntRect()); EXPECT_EQ(quadList.size(), 13u); } @@ -120,7 +120,7 @@ TEST(CCQuadCullerTest, verifyCullCenterTileOnly) setQuads(rootState.get(), childState.get(), quadList); EXPECT_EQ(quadList.size(), 13u); - CCQuadCuller::cullOccludedQuads(quadList); + CCQuadCuller::cullOccludedQuads(quadList, false, IntRect()); EXPECT_EQ(quadList.size(), 12u); IntRect quadVisibleRect1 = quadList[1].get()->quadVisibleRect(); @@ -158,7 +158,7 @@ TEST(CCQuadCullerTest, verifyCullCenterTileNonIntegralSize1) quadList.append(MakeTileQuad(childState.get(), IntRect(IntPoint(), IntSize(100, 100)))); EXPECT_EQ(quadList.size(), 2u); - CCQuadCuller::cullOccludedQuads(quadList); + CCQuadCuller::cullOccludedQuads(quadList, false, IntRect()); EXPECT_EQ(quadList.size(), 2u); } @@ -181,7 +181,7 @@ TEST(CCQuadCullerTest, verifyCullCenterTileNonIntegralSize2) quadList.append(MakeTileQuad(childState.get(), IntRect(IntPoint(), IntSize(100, 100)))); EXPECT_EQ(quadList.size(), 2u); - CCQuadCuller::cullOccludedQuads(quadList); + CCQuadCuller::cullOccludedQuads(quadList, false, IntRect()); EXPECT_EQ(quadList.size(), 2u); } @@ -196,7 +196,7 @@ TEST(CCQuadCullerTest, verifyCullChildLinesUpBottomRight) setQuads(rootState.get(), childState.get(), quadList); EXPECT_EQ(quadList.size(), 13u); - CCQuadCuller::cullOccludedQuads(quadList); + CCQuadCuller::cullOccludedQuads(quadList, false, IntRect()); EXPECT_EQ(quadList.size(), 9u); } @@ -212,7 +212,7 @@ TEST(CCQuadCullerTest, verifyCullSubRegion) setQuads(rootState.get(), childState.get(), quadList, childOpaqueRect); EXPECT_EQ(quadList.size(), 13u); - CCQuadCuller::cullOccludedQuads(quadList); + CCQuadCuller::cullOccludedQuads(quadList, false, IntRect()); EXPECT_EQ(quadList.size(), 12u); } @@ -228,7 +228,7 @@ TEST(CCQuadCullerTest, verifyCullSubRegion2) setQuads(rootState.get(), childState.get(), quadList, childOpaqueRect); EXPECT_EQ(quadList.size(), 13u); - CCQuadCuller::cullOccludedQuads(quadList); + CCQuadCuller::cullOccludedQuads(quadList, false, IntRect()); EXPECT_EQ(quadList.size(), 12u); } @@ -244,7 +244,7 @@ TEST(CCQuadCullerTest, verifyCullSubRegionCheckOvercull) setQuads(rootState.get(), childState.get(), quadList, childOpaqueRect); EXPECT_EQ(quadList.size(), 13u); - CCQuadCuller::cullOccludedQuads(quadList); + CCQuadCuller::cullOccludedQuads(quadList, false, IntRect()); EXPECT_EQ(quadList.size(), 13u); } @@ -260,7 +260,7 @@ TEST(CCQuadCullerTest, verifyNonAxisAlignedQuadsDontOcclude) setQuads(rootState.get(), childState.get(), quadList); EXPECT_EQ(quadList.size(), 13u); - CCQuadCuller::cullOccludedQuads(quadList); + CCQuadCuller::cullOccludedQuads(quadList, false, IntRect()); EXPECT_EQ(quadList.size(), 13u); } @@ -282,8 +282,61 @@ TEST(CCQuadCullerTest, verifyNonAxisAlignedQuadsSafelyCulled) setQuads(rootState.get(), childState.get(), quadList); EXPECT_EQ(quadList.size(), 13u); - CCQuadCuller::cullOccludedQuads(quadList); + CCQuadCuller::cullOccludedQuads(quadList, false, IntRect()); EXPECT_EQ(quadList.size(), 12u); } +TEST(CCQuadCullerTest, veriftyCullOutsideScissorOverTile) +{ + DECLARE_AND_INITIALIZE_TEST_QUADS + + OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true); + OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true); + + setQuads(rootState.get(), childState.get(), quadList); + EXPECT_EQ(quadList.size(), 13u); + CCQuadCuller::cullOccludedQuads(quadList, true, IntRect(200, 100, 100, 100)); + EXPECT_EQ(quadList.size(), 1u); +} + +TEST(CCQuadCullerTest, veriftyCullOutsideScissorOverCulledTile) +{ + DECLARE_AND_INITIALIZE_TEST_QUADS + + OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true); + OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true); + + setQuads(rootState.get(), childState.get(), quadList); + EXPECT_EQ(quadList.size(), 13u); + CCQuadCuller::cullOccludedQuads(quadList, true, IntRect(100, 100, 100, 100)); + EXPECT_EQ(quadList.size(), 1u); +} + +TEST(CCQuadCullerTest, veriftyCullOutsideScissorOverPartialTiles) +{ + DECLARE_AND_INITIALIZE_TEST_QUADS + + OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true); + OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true); + + setQuads(rootState.get(), childState.get(), quadList); + EXPECT_EQ(quadList.size(), 13u); + CCQuadCuller::cullOccludedQuads(quadList, true, IntRect(50, 50, 200, 200)); + EXPECT_EQ(quadList.size(), 9u); +} + +TEST(CCQuadCullerTest, veriftyCullOutsideScissorOverNoTiles) +{ + DECLARE_AND_INITIALIZE_TEST_QUADS + + OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(TransformationMatrix(), TransformationMatrix(), rootRect, IntRect(), 1.0, true); + OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true); + + setQuads(rootState.get(), childState.get(), quadList); + EXPECT_EQ(quadList.size(), 13u); + CCQuadCuller::cullOccludedQuads(quadList, true, IntRect(500, 500, 100, 100)); + EXPECT_EQ(quadList.size(), 0u); +} + + } // namespace diff --git a/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp b/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp index 4b3dd27d3..ec0ce0c6a 100644 --- a/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp +++ b/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp @@ -79,8 +79,8 @@ protected: { GraphicsContext3D::Attributes attrs; - RefPtr<GraphicsContext3D> mainContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread); - RefPtr<GraphicsContext3D> implContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread); + RefPtr<GraphicsContext3D> mainContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), GraphicsContext3D::RenderDirectlyToHostWindow); + RefPtr<GraphicsContext3D> implContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), GraphicsContext3D::RenderDirectlyToHostWindow); MockCanvasContext& mainMock = *static_cast<MockCanvasContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(mainContext.get())); MockCanvasContext& implMock = *static_cast<MockCanvasContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(implContext.get())); diff --git a/Source/WebKit/chromium/tests/CompositorFakeGraphicsContext3D.h b/Source/WebKit/chromium/tests/CompositorFakeGraphicsContext3D.h index 1f0897341..937b62d4c 100644 --- a/Source/WebKit/chromium/tests/CompositorFakeGraphicsContext3D.h +++ b/Source/WebKit/chromium/tests/CompositorFakeGraphicsContext3D.h @@ -37,10 +37,7 @@ static PassRefPtr<GraphicsContext3D> createCompositorMockGraphicsContext3D(Graph webAttrs.alpha = attrs.alpha; OwnPtr<WebKit::WebGraphicsContext3D> webContext = WebKit::CompositorFakeWebGraphicsContext3D::create(webAttrs); - return GraphicsContext3DPrivate::createGraphicsContextFromWebContext( - webContext.release(), attrs, 0, - GraphicsContext3D::RenderDirectlyToHostWindow, - GraphicsContext3DPrivate::ForUseOnAnotherThread); + return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(webContext.release(), GraphicsContext3D::RenderDirectlyToHostWindow); } } diff --git a/Source/WebKit/chromium/tests/FakeGraphicsContext3DTest.cpp b/Source/WebKit/chromium/tests/FakeGraphicsContext3DTest.cpp index 2b76b80ad..71cb8bab1 100644 --- a/Source/WebKit/chromium/tests/FakeGraphicsContext3DTest.cpp +++ b/Source/WebKit/chromium/tests/FakeGraphicsContext3DTest.cpp @@ -52,7 +52,7 @@ private: TEST(FakeGraphicsContext3DTest, CanOverrideManually) { GraphicsContext3D::Attributes attrs; - RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FrameCountingContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread); + RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FrameCountingContext()), GraphicsContext3D::RenderDirectlyToHostWindow); FrameCountingContext& mockContext = *static_cast<FrameCountingContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(context.get())); for (int i = 0; i < 10; i++) { @@ -73,7 +73,7 @@ public: TEST(FakeGraphicsContext3DTest, CanUseGMock) { GraphicsContext3D::Attributes attrs; - RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new GMockContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread); + RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new GMockContext()), GraphicsContext3D::RenderDirectlyToHostWindow); GMockContext& mockContext = *static_cast<GMockContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(context.get())); EXPECT_CALL(mockContext, getError()) @@ -104,7 +104,7 @@ private: TEST(FakeGraphicsContext3DTest, ContextForThisThreadShouldNotMakeCurrent) { GraphicsContext3D::Attributes attrs; - RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new ContextThatCountsMakeCurrents()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread); + RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new ContextThatCountsMakeCurrents()), GraphicsContext3D::RenderDirectlyToHostWindow); EXPECT_TRUE(context); ContextThatCountsMakeCurrents& mockContext = *static_cast<ContextThatCountsMakeCurrents*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(context.get())); EXPECT_EQ(0, mockContext.makeCurrentCount()); @@ -113,7 +113,7 @@ TEST(FakeGraphicsContext3DTest, ContextForThisThreadShouldNotMakeCurrent) TEST(FakeGraphicsContext3DTest, ContextForAnotherThreadShouldNotMakeCurrent) { GraphicsContext3D::Attributes attrs; - RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new ContextThatCountsMakeCurrents()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnAnotherThread); + RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new ContextThatCountsMakeCurrents()), GraphicsContext3D::RenderDirectlyToHostWindow); EXPECT_TRUE(context); ContextThatCountsMakeCurrents& mockContext = *static_cast<ContextThatCountsMakeCurrents*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(context.get())); EXPECT_EQ(0, mockContext.makeCurrentCount()); diff --git a/Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h b/Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h index cf0651b77..ae27da730 100644 --- a/Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h +++ b/Source/WebKit/chromium/tests/FakeWebGraphicsContext3D.h @@ -65,6 +65,8 @@ public: virtual void setVisibilityCHROMIUM(bool visible) { } + virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { } + virtual WebString getRequestableExtensionsCHROMIUM() { return WebString(); } virtual void requestExtensionCHROMIUM(const char*) { } diff --git a/Source/WebKit/chromium/tests/LayerChromiumTest.cpp b/Source/WebKit/chromium/tests/LayerChromiumTest.cpp index 43083a1d7..2e9ca9661 100644 --- a/Source/WebKit/chromium/tests/LayerChromiumTest.cpp +++ b/Source/WebKit/chromium/tests/LayerChromiumTest.cpp @@ -515,6 +515,7 @@ TEST_F(LayerChromiumTest, checkPropertyChangeCausesCorrectBehavior) EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setReplicaLayer(dummyLayer.get())); EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setSublayerTransform(TransformationMatrix(0, 0, 0, 0, 0, 0))); EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setScrollable(true)); + EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setHaveWheelEventHandlers(true)); EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setScrollPosition(IntPoint(10, 10))); EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setTransform(TransformationMatrix(0, 0, 0, 0, 0, 0))); EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setDoubleSided(false)); @@ -539,10 +540,21 @@ public: return true; } + virtual void setNeedsDisplayRect(const FloatRect& dirtyRect) + { + m_lastNeedsDisplayRect = dirtyRect; + LayerChromium::setNeedsDisplayRect(dirtyRect); + } + void resetNeedsDisplay() { m_needsDisplay = false; } + + const FloatRect& lastNeedsDisplayRect() const { return m_lastNeedsDisplayRect; } + +private: + FloatRect m_lastNeedsDisplayRect; }; TEST_F(LayerChromiumTest, checkContentsScaleChangeTriggersNeedsDisplay) @@ -558,6 +570,7 @@ TEST_F(LayerChromiumTest, checkContentsScaleChangeTriggersNeedsDisplay) EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setContentsScale(testLayer->contentsScale() + 1.f)); EXPECT_TRUE(testLayer->needsDisplay()); + EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 320, 240), testLayer->lastNeedsDisplayRect()); } class FakeCCLayerTreeHost : public CCLayerTreeHost { diff --git a/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp b/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp index 924b42d28..d097c499a 100644 --- a/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp +++ b/Source/WebKit/chromium/tests/PlatformContextSkiaTest.cpp @@ -163,6 +163,30 @@ TEST(PlatformContextSkiaTest, trackOpaqueClipTest) context.clearRect(FloatRect(10, 10, 90, 90)); EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect()); + // The transform and the clip need to interact correctly (transform first) + context.save(); + context.translate(10, 10); + context.clip(FloatRect(20, 20, 10, 10)); + context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver); + EXPECT_EQ_RECT(IntRect(30, 30, 10, 10), platformContext.opaqueRegion().asRect()); + EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect()); + context.restore(); + + context.clearRect(FloatRect(10, 10, 90, 90)); + EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect()); + + // The transform and the clip need to interact correctly (clip first) + context.save(); + context.clip(FloatRect(20, 20, 10, 10)); + context.translate(10, 10); + context.fillRect(FloatRect(10, 10, 90, 90), opaque, ColorSpaceDeviceRGB, CompositeSourceOver); + EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), platformContext.opaqueRegion().asRect()); + EXPECT_PIXELS_MATCH(bitmap, platformContext.opaqueRegion().asRect()); + context.restore(); + + context.clearRect(FloatRect(10, 10, 90, 90)); + EXPECT_EQ_RECT(IntRect(), platformContext.opaqueRegion().asRect()); + Path path; path.moveTo(FloatPoint(0, 0)); path.addLineTo(FloatPoint(100, 0)); diff --git a/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp b/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp index fcd3878a6..e03559046 100644 --- a/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp +++ b/Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp @@ -162,6 +162,14 @@ public: return TiledLayerChromium::skipsDraw(); } + virtual void setNeedsDisplayRect(const FloatRect& rect) + { + m_lastNeedsDisplayRect = rect; + TiledLayerChromium::setNeedsDisplayRect(rect); + } + + const FloatRect& lastNeedsDisplayRect() const { return m_lastNeedsDisplayRect; } + FakeLayerTextureUpdater* fakeLayerTextureUpdater() { return m_fakeTextureUpdater.get(); } virtual TextureManager* textureManager() const { return m_textureManager; } @@ -181,6 +189,7 @@ private: RefPtr<FakeLayerTextureUpdater> m_fakeTextureUpdater; TextureManager* m_textureManager; + FloatRect m_lastNeedsDisplayRect; }; class FakeTiledLayerWithScaledBounds : public FakeTiledLayerChromium { @@ -434,6 +443,57 @@ TEST(TiledLayerChromiumTest, verifyUpdateRectWhenContentBoundsAreScaled) EXPECT_FLOAT_RECT_EQ(FloatRect(45, 80, 15, 8), layer->updateRect()); } +TEST(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges) +{ + OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024); + RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get())); + DebugScopedSetImplThread implThread; + RefPtr<FakeCCTiledLayerImpl> layerImpl = adoptRef(new FakeCCTiledLayerImpl(0)); + + FakeTextureAllocator textureAllocator; + CCTextureUpdater updater(&textureAllocator); + + // Create a layer with one tile. + layer->setBounds(IntSize(100, 100)); + + // Invalidate the entire layer. + layer->setNeedsDisplay(); + EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect()); + + // Push the tiles to the impl side and check that there is exactly one. + layer->prepareToUpdate(IntRect(0, 0, 100, 100)); + layer->updateCompositorResources(0, updater); + layer->pushPropertiesTo(layerImpl.get()); + EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); + EXPECT_FALSE(layerImpl->hasTileAt(0, 1)); + EXPECT_FALSE(layerImpl->hasTileAt(1, 0)); + EXPECT_FALSE(layerImpl->hasTileAt(1, 1)); + + // Change the contents scale and verify that the content rectangle requiring painting + // is not scaled. + layer->setContentsScale(2); + EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect()); + + // The impl side should get 2x2 tiles now. + layer->prepareToUpdate(IntRect(0, 0, 200, 200)); + layer->updateCompositorResources(0, updater); + layer->pushPropertiesTo(layerImpl.get()); + EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); + EXPECT_TRUE(layerImpl->hasTileAt(0, 1)); + EXPECT_TRUE(layerImpl->hasTileAt(1, 0)); + EXPECT_TRUE(layerImpl->hasTileAt(1, 1)); + + // Invalidate the entire layer again, but do not paint. All tiles should be gone now from the + // impl side. + layer->setNeedsDisplay(); + layer->updateCompositorResources(0, updater); + layer->pushPropertiesTo(layerImpl.get()); + EXPECT_FALSE(layerImpl->hasTileAt(0, 0)); + EXPECT_FALSE(layerImpl->hasTileAt(0, 1)); + EXPECT_FALSE(layerImpl->hasTileAt(1, 0)); + EXPECT_FALSE(layerImpl->hasTileAt(1, 1)); +} + TEST(TiledLayerChromiumTest, skipsDrawGetsReset) { // Initialize without threading support. @@ -524,7 +584,7 @@ TEST(TiledLayerChromiumTest, layerAddsSelfToOccludedRegion) occluded = Region(); layer->addSelfToOccludedScreenSpace(occluded); EXPECT_EQ_RECT(IntRect(), occluded.bounds()); - EXPECT_EQ(1u, occluded.rects().size()); + EXPECT_EQ(0u, occluded.rects().size()); // If the layer paints opaque content, then the occluded region should match the visible opaque content. IntRect opaquePaintRect = IntRect(10, 10, 90, 190); @@ -546,6 +606,28 @@ TEST(TiledLayerChromiumTest, layerAddsSelfToOccludedRegion) EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), occluded.bounds()); EXPECT_EQ(1u, occluded.rects().size()); + // If we repaint a non-opaque part of the tile, then it shouldn't lose its opaque-ness. And other tiles should + // not be affected. + layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect()); + layer->invalidateRect(IntRect(0, 0, 1, 1)); + layer->prepareToUpdate(contentBounds); + + occluded = Region(); + layer->addSelfToOccludedScreenSpace(occluded); + EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), occluded.bounds()); + EXPECT_EQ(1u, occluded.rects().size()); + + // If we repaint an opaque part of the tile, then it should lose its opaque-ness. But other tiles should still + // not be affected. + layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect()); + layer->invalidateRect(IntRect(10, 10, 1, 1)); + layer->prepareToUpdate(contentBounds); + + occluded = Region(); + layer->addSelfToOccludedScreenSpace(occluded); + EXPECT_EQ_RECT(intersection(IntRect(10, 100, 90, 100), visibleBounds), occluded.bounds()); + EXPECT_EQ(1u, occluded.rects().size()); + // If the layer is transformed then the resulting occluded area needs to be transformed to its target space. TransformationMatrix transform; transform.translate(contentBounds.width() / 2.0, contentBounds.height() / 2.0); @@ -556,6 +638,8 @@ TEST(TiledLayerChromiumTest, layerAddsSelfToOccludedRegion) screenSpaceTransform *= transform; screenSpaceTransform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0); layer->setScreenSpaceTransform(screenSpaceTransform); + layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect); + layer->invalidateRect(opaquePaintRect); layer->prepareToUpdate(contentBounds); occluded = Region(); diff --git a/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp b/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp index 1557a7d93..4724b4a43 100644 --- a/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp +++ b/Source/WebKit/chromium/tests/TreeSynchronizerTest.cpp @@ -26,13 +26,16 @@ #include "TreeSynchronizer.h" +#include "CCAnimationTestCommon.h" #include "LayerChromium.h" +#include "cc/CCLayerAnimationController.h" #include "cc/CCLayerImpl.h" #include "cc/CCProxy.h" #include "cc/CCSingleThreadProxy.h" #include <gtest/gtest.h> using namespace WebCore; +using namespace WebKitTests; namespace { @@ -91,6 +94,30 @@ private: Vector<int>* m_ccLayerDestructionList; }; +class FakeLayerAnimationController : public CCLayerAnimationController { +public: + static PassOwnPtr<FakeLayerAnimationController> create() + { + return adoptPtr(new FakeLayerAnimationController); + } + + bool synchronizedAnimations() const { return m_synchronizedAnimations; } + +private: + FakeLayerAnimationController() + : m_synchronizedAnimations(false) + { + } + + virtual void synchronizeAnimations(CCLayerAnimationControllerImpl* controllerImpl) + { + CCLayerAnimationController::synchronizeAnimations(controllerImpl); + m_synchronizedAnimations = true; + } + + bool m_synchronizedAnimations; +}; + void expectTreesAreIdentical(LayerChromium* layer, CCLayerImpl* ccLayer) { ASSERT_TRUE(layer); @@ -307,5 +334,19 @@ TEST(TreeSynchronizerTest, syncMaskReplicaAndReplicaMaskLayers) expectTreesAreIdentical(layerTreeRoot.get(), ccLayerTreeRoot.get()); } +TEST(TreeSynchronizerTest, synchronizeAnimations) +{ + DebugScopedSetImplThread impl; + RefPtr<LayerChromium> layerTreeRoot = LayerChromium::create(); + + layerTreeRoot->setLayerAnimationController(FakeLayerAnimationController::create()); + + EXPECT_FALSE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations()); + + RefPtr<CCLayerImpl> ccLayerTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), 0); + ccLayerTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), ccLayerTreeRoot.get()); + + EXPECT_TRUE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations()); +} } // namespace diff --git a/Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp b/Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp index ad5810524..459255e02 100644 --- a/Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp +++ b/Source/WebKit/chromium/tests/WebCompositorInputHandlerImplTest.cpp @@ -67,14 +67,13 @@ public: private: virtual void setNeedsRedraw() OVERRIDE { } - virtual ScrollStatus scrollBegin(const WebCore::IntPoint&) OVERRIDE + virtual ScrollStatus scrollBegin(const WebCore::IntPoint&, WebCore::CCInputHandlerClient::ScrollInputType) OVERRIDE { return m_scrollStatus; } virtual void scrollBy(const WebCore::IntSize&) OVERRIDE { } virtual void scrollEnd() OVERRIDE { } - virtual bool haveWheelEventHandlers() OVERRIDE { return false; } virtual void pinchGestureBegin() OVERRIDE { m_pinchStarted = true; diff --git a/Source/WebKit/chromium/tests/WebFrameTest.cpp b/Source/WebKit/chromium/tests/WebFrameTest.cpp index b59001860..f61e98648 100644 --- a/Source/WebKit/chromium/tests/WebFrameTest.cpp +++ b/Source/WebKit/chromium/tests/WebFrameTest.cpp @@ -151,6 +151,78 @@ TEST_F(WebFrameTest, ChromePageNoJavascript) EXPECT_EQ(std::string::npos, content.find("Clobbered")); } +#if ENABLE(GESTURE_EVENTS) +TEST_F(WebFrameTest, DivAutoZoomParamsTest) +{ + registerMockedHttpURLLoad("get_scale_for_auto_zoom_into_div_test.html"); + + WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(FrameTestHelpers::createWebViewAndLoad(m_baseURL + "get_scale_for_auto_zoom_into_div_test.html", true)); + int pageWidth = 640; + int pageHeight = 480; + int divPosX = 200; + int divPosY = 200; + int divWidth = 200; + int divHeight = 150; + WebRect doubleTapPoint(250, 250, 0, 0); + webViewImpl->resize(WebSize(pageWidth, pageHeight)); + float scale; + WebPoint scroll; + + // Test for Doubletap scaling + + // Tests for zooming in and out without clamping. + // Set device scale and scale limits so we dont get clamped. + webViewImpl->setDeviceScaleFactor(4); + webViewImpl->setPageScaleFactorLimits(0, 4 / webViewImpl->deviceScaleFactor()); + + // Test zooming into div. + webViewImpl->computeScaleAndScrollForHitRect(doubleTapPoint, WebViewImpl::DoubleTap, scale, scroll); + float scaledDivWidth = divWidth * scale; + float scaledDivHeight = divHeight * scale; + int hScroll = ((divPosX * scale) - ((pageWidth - scaledDivWidth) / 2)) / scale; + int vScroll = ((divPosY * scale) - ((pageHeight - scaledDivHeight) / 2)) / scale; + EXPECT_NEAR(pageWidth / divWidth, scale, 0.1); + EXPECT_EQ(hScroll, scroll.x); + EXPECT_EQ(vScroll, scroll.y); + + // Test zoom out to overview scale. + webViewImpl->applyScrollAndScale(WebCore::IntSize(scroll.x, scroll.y), scale / webViewImpl->pageScaleFactor()); + webViewImpl->computeScaleAndScrollForHitRect(doubleTapPoint, WebViewImpl::DoubleTap, scale, scroll); + EXPECT_FLOAT_EQ(1, scale); + EXPECT_EQ(WebPoint(0, 0), scroll); + + // Tests for clamped scaling. + // Test clamp to device scale: + webViewImpl->applyScrollAndScale(WebCore::IntSize(scroll.x, scroll.y), scale / webViewImpl->pageScaleFactor()); + webViewImpl->setDeviceScaleFactor(2.5); + webViewImpl->computeScaleAndScrollForHitRect(doubleTapPoint, WebViewImpl::DoubleTap, scale, scroll); + EXPECT_FLOAT_EQ(2.5, scale); + + // Test clamp to minimum scale: + webViewImpl->applyScrollAndScale(WebCore::IntSize(scroll.x, scroll.y), scale / webViewImpl->pageScaleFactor()); + webViewImpl->setPageScaleFactorLimits(1.5 / webViewImpl->deviceScaleFactor(), 4 / webViewImpl->deviceScaleFactor()); + webViewImpl->computeScaleAndScrollForHitRect(doubleTapPoint, WebViewImpl::DoubleTap, scale, scroll); + EXPECT_FLOAT_EQ(1.5, scale); + EXPECT_EQ(WebPoint(0, 0), scroll); + + // Test clamp to maximum scale: + webViewImpl->applyScrollAndScale(WebCore::IntSize(scroll.x, scroll.y), scale / webViewImpl->pageScaleFactor()); + webViewImpl->setDeviceScaleFactor(4); + webViewImpl->setPageScaleFactorLimits(0, 3 / webViewImpl->deviceScaleFactor()); + webViewImpl->computeScaleAndScrollForHitRect(doubleTapPoint, WebViewImpl::DoubleTap, scale, scroll); + EXPECT_FLOAT_EQ(3, scale); + + + // Test for Non-doubletap scaling + webViewImpl->setPageScaleFactor(1, WebPoint(0, 0)); + webViewImpl->setDeviceScaleFactor(4); + webViewImpl->setPageScaleFactorLimits(0, 4 / webViewImpl->deviceScaleFactor()); + // Test zooming into div. + webViewImpl->computeScaleAndScrollForHitRect(WebRect(250, 250, 10, 10), WebViewImpl::FindInPage, scale, scroll); + EXPECT_NEAR(pageWidth / divWidth, scale, 0.1); +} +#endif + class TestReloadDoesntRedirectWebFrameClient : public WebFrameClient { public: virtual WebNavigationPolicy decidePolicyForNavigation( diff --git a/Source/WebKit/chromium/tests/WebSocketDeflaterTest.cpp b/Source/WebKit/chromium/tests/WebSocketDeflaterTest.cpp new file mode 100644 index 000000000..423a5969f --- /dev/null +++ b/Source/WebKit/chromium/tests/WebSocketDeflaterTest.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "WebSocketDeflater.h" + +#include <gtest/gtest.h> +#include <wtf/Vector.h> + +using namespace WebCore; + +namespace { + +TEST(WebSocketDeflaterTest, TestCompressHello) +{ + // Test the first example on section 4.3 of the specification. + OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15); + ASSERT_TRUE(deflater->initialize()); + OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create(); + ASSERT_TRUE(inflater->initialize()); + const char* inputData = "Hello"; + const size_t inputLength = strlen(inputData); + + ASSERT_TRUE(deflater->addBytes(inputData, inputLength)); + ASSERT_TRUE(deflater->finish()); + const char expectedFirst[] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00}; + EXPECT_EQ(sizeof(expectedFirst), deflater->size()); + EXPECT_EQ(0, memcmp(expectedFirst, deflater->data(), deflater->size())); + ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size())); + ASSERT_TRUE(inflater->finish()); + EXPECT_EQ(inputLength, inflater->size()); + EXPECT_EQ(0, memcmp(inputData, inflater->data(), inflater->size())); + + deflater->reset(); + inflater->reset(); + + ASSERT_TRUE(deflater->addBytes(inputData, inputLength)); + ASSERT_TRUE(deflater->finish()); + const char expectedSecond[] = {0xf2, 0x00, 0x11, 0x00, 0x00}; + EXPECT_EQ(sizeof(expectedSecond), deflater->size()); + EXPECT_EQ(0, memcmp(expectedSecond, deflater->data(), deflater->size())); + ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size())); + ASSERT_TRUE(inflater->finish()); + EXPECT_EQ(inputLength, inflater->size()); + EXPECT_EQ(0, memcmp(inputData, inflater->data(), inflater->size())); +} + +TEST(WebSocketDeflaterTest, TestMultipleAddBytesCalls) +{ + OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15); + ASSERT_TRUE(deflater->initialize()); + OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create(); + ASSERT_TRUE(inflater->initialize()); + Vector<char> inputData(32); + inputData.fill('a'); + + for (size_t i = 0; i < inputData.size(); ++i) + ASSERT_TRUE(deflater->addBytes(inputData.data() + i, 1)); + ASSERT_TRUE(deflater->finish()); + for (size_t i = 0; i < deflater->size(); ++i) + ASSERT_TRUE(inflater->addBytes(deflater->data() + i, 1)); + ASSERT_TRUE(inflater->finish()); + EXPECT_EQ(inputData.size(), inflater->size()); + EXPECT_EQ(0, memcmp(inputData.data(), inflater->data(), inflater->size())); +} + +TEST(WebSocketDeflaterTest, TestNoContextTakeOver) +{ + OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15, WebSocketDeflater::DoNotTakeOverContext); + ASSERT_TRUE(deflater->initialize()); + OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create(); + ASSERT_TRUE(inflater->initialize()); + const char expected[] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00}; + const char* inputData = "Hello"; + const size_t inputLength = strlen(inputData); + + // If we don't take over context, the second result should be the identical + // with the first one. + for (size_t i = 0; i < 2; ++i) { + ASSERT_TRUE(deflater->addBytes(inputData, inputLength)); + ASSERT_TRUE(deflater->finish()); + EXPECT_EQ(sizeof(expected), deflater->size()); + EXPECT_EQ(0, memcmp(expected, deflater->data(), deflater->size())); + ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size())); + ASSERT_TRUE(inflater->finish()); + EXPECT_EQ(inputLength, inflater->size()); + EXPECT_EQ(0, memcmp(inputData, inflater->data(), inflater->size())); + deflater->reset(); + inflater->reset(); + } +} + +TEST(WebSocketDeflaterTest, TestWindowBits) +{ + Vector<char> inputData(1024 + 64 * 2); + inputData.fill('a'); + // Modify the head and tail of the inputData so that back-reference + // can be used if the window size is sufficiently-large. + for (size_t j = 0; j < 64; ++j) { + inputData[j] = 'b'; + inputData[inputData.size() - j - 1] = 'b'; + } + + OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(8); + ASSERT_TRUE(deflater->initialize()); + ASSERT_TRUE(deflater->addBytes(inputData.data(), inputData.size())); + ASSERT_TRUE(deflater->finish()); + + OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create(8); + ASSERT_TRUE(inflater->initialize()); + ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size())); + ASSERT_TRUE(inflater->finish()); + EXPECT_EQ(inputData.size(), inflater->size()); + EXPECT_EQ(0, memcmp(inputData.data(), inflater->data(), inflater->size())); +} + +TEST(WebSocketDeflaterTest, TestLargeData) +{ + OwnPtr<WebSocketDeflater> deflater = WebSocketDeflater::create(15); + ASSERT_TRUE(deflater->initialize()); + OwnPtr<WebSocketInflater> inflater = WebSocketInflater::create(); + ASSERT_TRUE(inflater->initialize()); + Vector<char> inputData(16 * 1024 * 1024); + inputData.fill('a'); + + ASSERT_TRUE(deflater->addBytes(inputData.data(), inputData.size())); + ASSERT_TRUE(deflater->finish()); + ASSERT_TRUE(inflater->addBytes(deflater->data(), deflater->size())); + ASSERT_TRUE(inflater->finish()); + EXPECT_EQ(inputData.size(), inflater->size()); + EXPECT_EQ(0, memcmp(inputData.data(), inflater->data(), inflater->size())); +} + +} diff --git a/Source/WebKit/chromium/tests/WebSocketExtensionDispatcherTest.cpp b/Source/WebKit/chromium/tests/WebSocketExtensionDispatcherTest.cpp new file mode 100644 index 000000000..358983b83 --- /dev/null +++ b/Source/WebKit/chromium/tests/WebSocketExtensionDispatcherTest.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "WebSocketExtensionDispatcher.h" + +#include "WebSocketExtensionProcessor.h" + +#include <gtest/gtest.h> +#include <wtf/text/StringHash.h> + +using namespace WebCore; + +namespace { + +class WebSocketExtensionDispatcherTest; + +class MockWebSocketExtensionProcessor : public WebSocketExtensionProcessor { +public: + MockWebSocketExtensionProcessor(const String& name, WebSocketExtensionDispatcherTest* test) + : WebSocketExtensionProcessor(name) + , m_test(test) + { + } + virtual String handshakeString() OVERRIDE { return extensionToken(); } + virtual bool processResponse(const HashMap<String, String>&) OVERRIDE; + +private: + WebSocketExtensionDispatcherTest* m_test; +}; + +class WebSocketExtensionDispatcherTest : public testing::Test { +public: + WebSocketExtensionDispatcherTest() { } + + void SetUp() { } + + void TearDown() { } + + void addMockProcessor(const String& extensionToken) + { + m_extensions.addProcessor(adoptPtr(new MockWebSocketExtensionProcessor(extensionToken, this))); + + } + + void appendResult(const String& extensionToken, const HashMap<String, String>& parameters) + { + m_parsedExtensionTokens.append(extensionToken); + m_parsedParameters.append(parameters); + } + +protected: + WebSocketExtensionDispatcher m_extensions; + Vector<String> m_parsedExtensionTokens; + Vector<HashMap<String, String> > m_parsedParameters; +}; + +bool MockWebSocketExtensionProcessor::processResponse(const HashMap<String, String>& parameters) +{ + m_test->appendResult(extensionToken(), parameters); + return true; +} + +TEST_F(WebSocketExtensionDispatcherTest, TestSingle) +{ + addMockProcessor("deflate-frame"); + EXPECT_TRUE(m_extensions.processHeaderValue("deflate-frame")); + EXPECT_EQ(1UL, m_parsedExtensionTokens.size()); + EXPECT_EQ("deflate-frame", m_parsedExtensionTokens[0]); + EXPECT_EQ("deflate-frame", m_extensions.acceptedExtensions()); + EXPECT_EQ(0, m_parsedParameters[0].size()); +} + +TEST_F(WebSocketExtensionDispatcherTest, TestParameters) +{ + addMockProcessor("mux"); + EXPECT_TRUE(m_extensions.processHeaderValue("mux; max-channels=4; flow-control ")); + EXPECT_EQ(1UL, m_parsedExtensionTokens.size()); + EXPECT_EQ("mux", m_parsedExtensionTokens[0]); + EXPECT_EQ(2, m_parsedParameters[0].size()); + HashMap<String, String>::iterator parameter = m_parsedParameters[0].find("max-channels"); + EXPECT_TRUE(parameter != m_parsedParameters[0].end()); + EXPECT_EQ("4", parameter->second); + parameter = m_parsedParameters[0].find("flow-control"); + EXPECT_TRUE(parameter != m_parsedParameters[0].end()); + EXPECT_TRUE(parameter->second.isNull()); +} + +TEST_F(WebSocketExtensionDispatcherTest, TestMultiple) +{ + struct { + String token; + HashMap<String, String> parameters; + } expected[2]; + expected[0].token = "mux"; + expected[0].parameters.add("max-channels", "4"); + expected[0].parameters.add("flow-control", String()); + expected[1].token = "deflate-frame"; + + addMockProcessor("mux"); + addMockProcessor("deflate-frame"); + EXPECT_TRUE(m_extensions.processHeaderValue("mux ; max-channels =4;flow-control, deflate-frame ")); + EXPECT_TRUE(m_extensions.acceptedExtensions().find("mux") != notFound); + EXPECT_TRUE(m_extensions.acceptedExtensions().find("deflate-frame") != notFound); + for (size_t i = 0; i < sizeof(expected) / sizeof(expected[0]); ++i) { + EXPECT_EQ(expected[i].token, m_parsedExtensionTokens[i]); + const HashMap<String, String>& expectedParameters = expected[i].parameters; + const HashMap<String, String>& parsedParameters = m_parsedParameters[i]; + EXPECT_EQ(expected[i].parameters.size(), m_parsedParameters[i].size()); + for (HashMap<String, String>::const_iterator iterator = expectedParameters.begin(); iterator != expectedParameters.end(); ++iterator) { + HashMap<String, String>::const_iterator parsed = parsedParameters.find(iterator->first); + EXPECT_TRUE(parsed != parsedParameters.end()); + if (iterator->second.isNull()) + EXPECT_TRUE(parsed->second.isNull()); + else + EXPECT_EQ(iterator->second, parsed->second); + } + } +} + +TEST_F(WebSocketExtensionDispatcherTest, TestQuotedString) +{ + addMockProcessor("x-foo"); + EXPECT_TRUE(m_extensions.processHeaderValue("x-foo; param1=\"quoted string\"; param2=\"\\\"quoted\\\" string\\\\\"")); + EXPECT_EQ(2, m_parsedParameters[0].size()); + EXPECT_EQ("quoted string", m_parsedParameters[0].get("param1")); + EXPECT_EQ("\"quoted\" string\\", m_parsedParameters[0].get("param2")); +} + +TEST_F(WebSocketExtensionDispatcherTest, TestInvalid) +{ + const char* inputs[] = { + "\"x-foo\"", + "x-baz", + "x-foo\\", + "x-(foo)", + "x-foo; ", + "x-foo; bar=", + "x-foo; bar=x y", + "x-foo; bar=\"mismatch quote", + "x-foo; bar=\"\\\"", + "x-foo; \"bar\"=baz", + "x-foo x-bar", + "x-foo, x-baz" + "x-foo, ", + }; + for (size_t i = 0; i < sizeof(inputs) / sizeof(inputs[0]); ++i) { + m_extensions.reset(); + addMockProcessor("x-foo"); + addMockProcessor("x-bar"); + EXPECT_FALSE(m_extensions.processHeaderValue(inputs[i])); + EXPECT_TRUE(m_extensions.acceptedExtensions().isNull()); + } +} + +} diff --git a/Source/WebKit/chromium/tests/WebURLResponseTest.cpp b/Source/WebKit/chromium/tests/WebURLResponseTest.cpp new file mode 100644 index 000000000..112ed8601 --- /dev/null +++ b/Source/WebKit/chromium/tests/WebURLResponseTest.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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 + * OWNER 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 "platform/WebURLResponse.h" + +#include <gtest/gtest.h> + +using namespace WebKit; + +namespace { + +class TestExtraData : public WebURLResponse::ExtraData { +public: + explicit TestExtraData(bool* alive) + : m_alive(alive) + { + *alive = true; + } + + virtual ~TestExtraData() { *m_alive = false; } + +private: + bool* m_alive; +}; + +TEST(WebURLResponseTest, ExtraData) +{ + bool alive = false; + { + WebURLResponse urlResponse; + TestExtraData* extraData = new TestExtraData(&alive); + EXPECT_TRUE(alive); + + urlResponse.initialize(); + urlResponse.setExtraData(extraData); + EXPECT_EQ(extraData, urlResponse.extraData()); + { + WebURLResponse otherUrlResponse = urlResponse; + EXPECT_TRUE(alive); + EXPECT_EQ(extraData, otherUrlResponse.extraData()); + EXPECT_EQ(extraData, urlResponse.extraData()); + } + EXPECT_TRUE(alive); + EXPECT_EQ(extraData, urlResponse.extraData()); + } + EXPECT_FALSE(alive); +} + +} // namespace diff --git a/Source/WebKit/chromium/tests/data/get_scale_for_auto_zoom_into_div_test.html b/Source/WebKit/chromium/tests/data/get_scale_for_auto_zoom_into_div_test.html new file mode 100644 index 000000000..1817dc47d --- /dev/null +++ b/Source/WebKit/chromium/tests/data/get_scale_for_auto_zoom_into_div_test.html @@ -0,0 +1,13 @@ +<html> + <body> + <div style="background-color: green; position: absolute; left: 0px; top: 0px; width: 640px; height: 480px"> + <p>Top Div</p> + <div style="background-color: white; position: absolute; left: 200px; top: 200px; width: 200px; height: 150px"> + <p id="innerDiv">Div to zoom to</p> + <div style="background-color: red; position: fixed; left: 220px; top: 350px; width: 160px; height: 40px"> + <p id="innerInnerDiv">Div NOT to zoom to</p> + </div> + </div> + </div> + </body> +</html> diff --git a/Source/WebKit/efl/ChangeLog b/Source/WebKit/efl/ChangeLog index 6a52fa252..db22d44eb 100644 --- a/Source/WebKit/efl/ChangeLog +++ b/Source/WebKit/efl/ChangeLog @@ -1,3 +1,245 @@ +2012-02-24 Shinya Kawanaka <shinyak@chromium.org> + + SpellCheckRequest needs to know the context where the spellcheck happened. + https://bugs.webkit.org/show_bug.cgi?id=79320 + + Reviewed by Hajime Morita. + + * WebCoreSupport/EditorClientEfl.h: + (WebCore::EditorClientEfl::requestCheckingOfString): + +2012-02-21 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/EditorClientEfl.cpp: + (WebCore::EditorClientEfl::shouldApplyStyle): + * WebCoreSupport/EditorClientEfl.h: + (EditorClientEfl): + +2012-02-22 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/EditorClientEfl.cpp: + (WebCore::EditorClientEfl::shouldApplyStyle): + * WebCoreSupport/EditorClientEfl.h: + (EditorClientEfl): + +2012-02-20 Kihong Kwon <kihong.kwon@samsung.com> + + Add a new API for the Vibration API(W3C). + https://bugs.webkit.org/show_bug.cgi?id=72010 + + Reviewed by Hajime Morita. + + Implementation for the Vibration API feature to the EFL-port layer. + http://dev.w3.org/2009/dap/vibration/ + There are two methods for vibration API. + - vibrate : Vibrate device for receiving as a parameter. + - cancelVibrate : Cancel current vibration. + + * CMakeListsEfl.txt: + * WebCoreSupport/VibrationClientEfl.cpp: Added. + (WebCore): + (WebCore::VibrationClientEfl::VibrationClientEfl): + (WebCore::VibrationClientEfl::vibrate): + (WebCore::VibrationClientEfl::cancelVibration): + (WebCore::VibrationClientEfl::vibrationDestroyed): + * WebCoreSupport/VibrationClientEfl.h: Added. + (WebCore): + (VibrationClientEfl): + (WebCore::VibrationClientEfl::~VibrationClientEfl): + * ewk/ewk_view.cpp: + (_Ewk_View_Private_Data): + (_ewk_view_priv_new): + +2012-02-17 Raphael Kubo da Costa <kubo@profusion.mobi> + + [EFL] Unreviewed, adapt to the changes introduced in r107973. + + SVN r107973 moved some libsoup feature initialization code to + WebCore, but only changed the GTK+ bits in WebKit. + + * ewk/ewk_main.cpp: + (_ewk_init_body): Do not initialize the content sniffer and the + decoder here, the initialization is now done in WebCore. + +2012-02-17 Raphael Kubo da Costa <kubo@profusion.mobi> + + Unreviewed, fix the build with ENABLE(DEVICE_ORIENTATION) after + r107518. The EFL EWS bot doesn't enable that flag, so the breakage + was not spotted earlier. + + * ewk/ewk_view.cpp: + (_Ewk_View_Private_Data): + (_ewk_view_priv_new): + +2012-01-31 Raphael Kubo da Costa <kubo@profusion.mobi> + + [soup] Add support for multiple SoupSessions. + https://bugs.webkit.org/show_bug.cgi?id=77341 + + Add the necessary infrastructure to support multiple SoupSessions. Each + WebView now has a "session" property, which defaults to + ResourceHandle::defaultSession() and can be changed to another + SoupSession by the user. + + Some API in ewk_network and ewk_view which required SoupSession to be a + valid type in the headers has now been moved inside #if USE(SOUP) + ifdefs so we can actually the required Soup header and avoid build + problems with duplicate typedefs. + + * CMakeListsEfl.txt: + * WebCoreSupport/FrameLoaderClientEfl.cpp: + (WebCore::FrameLoaderClientEfl::createNetworkingContext): + * WebCoreSupport/FrameNetworkingContextEfl.cpp: Copied from Source/WebKit/efl/WebCoreSupport/FrameNetworkingContextEfl.h. + (WebCore): + (WebCore::FrameNetworkingContextEfl::create): + (WebCore::FrameNetworkingContextEfl::FrameNetworkingContextEfl): + (WebCore::FrameNetworkingContextEfl::soupSession): + * WebCoreSupport/FrameNetworkingContextEfl.h: + (FrameNetworkingContextEfl): + * ewk/ewk_cookies.h: Mention this API is only valid with the + default SoupSession. + * ewk/ewk_network.cpp: + (ewk_network_default_soup_session_get): Define only if USE(SOUP) is set. + * ewk/ewk_network.h: Ditto, and mention this API is only valid with the + default SoupSession. + * ewk/ewk_view.cpp: + (_Ewk_View_Private_Data): + (_ewk_view_priv_new): + (ewk_view_soup_session_get): + (ewk_view_soup_session_set): + * ewk/ewk_view.h: + (): + +2012-02-15 Sadrul Habib Chowdhury <sadrul@chromium.org> + + Notify ChromeClient when touch-event handlers are installed/removed. + https://bugs.webkit.org/show_bug.cgi?id=77440 + + Reviewed by Darin Fisher and Ryosuke Niwa. + + * WebCoreSupport/ChromeClientEfl.h: + (WebCore::ChromeClientEfl::numTouchEventHandlersChanged): + +2012-02-15 Gustavo Lima Chaves <glima@profusion.mobi> + + [EFL] Add missing libsoup to (pkgconfig) dependency requirements + https://bugs.webkit.org/show_bug.cgi?id=78702 + + Unreviewed build fix. + + * ewebkit.pc.in: Now that bug 77874 had its patch landed, we + always require libsoup as a dependency for the EFL port. The + 'Require' session of this file has to contemplate that, otherwise + code linking with ewebkit will fail to lookup to libsoup's header + files. + +2012-02-13 Raphael Kubo da Costa <kubo@profusion.mobi> + + [CMake] Merge WebKitEfl.cmake into FindEFL.cmake. + https://bugs.webkit.org/show_bug.cgi?id=78566 + + Reviewed by Daniel Bates. + + * CMakeListsEfl.txt: Do not include WebKitEfl.cmake. + +2012-02-11 Nikolas Zimmermann <nzimmermann@rim.com> + + Convert svg/animations to use SMIL methods for driving the timeline + https://bugs.webkit.org/show_bug.cgi?id=78422 + + Reviewed by Dirk Schulze. + + Remove SVG animation sampling functionality provided for DRT, which no longer uses it. + Instead we switched the svg/animations tests to use SVGSVGElement.setCurrentTime. + + * WebCoreSupport/DumpRenderTreeSupportEfl.cpp: + * WebCoreSupport/DumpRenderTreeSupportEfl.h: + +2012-02-06 Raphael Kubo da Costa <kubo@profusion.mobi> + + [EFL] Drop support for the Curl network backend. + https://bugs.webkit.org/show_bug.cgi?id=77874 + + Reviewed by Eric Seidel. + + Nobody seems to be maintaining the Curl backend in WebCore, the + EFL port developers all seem to be using the Soup backend and the + port itself has many features which are only implemented for the + latter. + + * CMakeListsEfl.txt: Unconditionally build soup-dependent files + and always add the glib/soup include directories and libraries. + * WebCoreSupport/FrameLoaderClientEfl.cpp: + (WebCore::FrameLoaderClientEfl::dispatchDidReceiveResponse): + Remove USE(SOUP) checks. + * ewk/ewk_auth.cpp: + (ewk_auth_show_dialog_callback_set): Ditto. + (ewk_auth_credentials_set): Ditto. + * ewk/ewk_cookies.cpp: + (ewk_cookies_file_set): Ditto. + (ewk_cookies_clear): Ditto. + (ewk_cookies_get_all): Ditto. + (ewk_cookies_cookie_del): Ditto. + (ewk_cookies_cookie_free): Ditto. + (ewk_cookies_policy_set): Ditto. + (ewk_cookies_policy_get): Ditto. + * ewk/ewk_frame.cpp: + (ewk_frame_certificate_status_get): Ditto. + * ewk/ewk_main.cpp: + (_ewk_init_body): Ditto. + * ewk/ewk_network.cpp: + (ewk_network_proxy_uri_set): Ditto. + (ewk_network_proxy_uri_get): Ditto. + (ewk_network_tls_certificate_check_get): Ditto. + (ewk_network_tls_certificate_check_set): Ditto. + (ewk_network_tls_ca_certificates_path_get): Ditto. + (ewk_network_tls_ca_certificates_path_set): Ditto. + (ewk_network_default_soup_session_get): Ditto. + * ewk/ewk_network.h: Update apidox for + ewk_network_default_soup_session_get() now that libsoup is the + only available backend. + +2012-02-09 Gustavo Lima Chaves <glima@profusion.mobi> + + [EFL] Introducing functions to set local storage db path and clear + those dbs. + https://bugs.webkit.org/show_bug.cgi?id=77107 + + This patch exposes the web local storage tracker database path + setting cabability, introduced on bug 77006, to the EFL port of + WebKit. Particularly, we have our own storage tracker client + object, to initialize the storage tracker backend on ewk_init(). + + Reviewed by Kenneth Rohde Christiansen. + + * CMakeListsEfl.txt: + * WebCoreSupport/StorageTrackerClientEfl.cpp: Added. + (WebCore): + (WebCore::StorageTrackerClientEfl::dispatchDidModifyOrigin): + (WebCore::StorageTrackerClientEfl::didFinishLoadingOrigins): + * WebCoreSupport/StorageTrackerClientEfl.h: Added. + (WebCore): + (StorageTrackerClientEfl): + * ewk/ewk_main.cpp: + (trackerClient): + (_ewk_init_body): + * ewk/ewk_settings.cpp: + (ewk_settings_local_storage_path_set): + (ewk_settings_local_storage_path_get): + (ewk_settings_local_storage_database_clear): + (ewk_settings_local_storage_database_origin_clear): + * ewk/ewk_settings.h: + 2012-02-07 Krzysztof Czech <k.czech@samsung.com> [EFL] Add missing initialization of editable variable. diff --git a/Source/WebKit/efl/WebCoreSupport/ChromeClientEfl.h b/Source/WebKit/efl/WebCoreSupport/ChromeClientEfl.h index 4b47c731c..82512251f 100644 --- a/Source/WebKit/efl/WebCoreSupport/ChromeClientEfl.h +++ b/Source/WebKit/efl/WebCoreSupport/ChromeClientEfl.h @@ -173,6 +173,7 @@ public: virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; } virtual void numWheelEventHandlersChanged(unsigned) { } + virtual void numTouchEventHandlersChanged(unsigned) { } Evas_Object* m_view; KURL m_hoveredLinkURL; diff --git a/Source/WebKit/efl/WebCoreSupport/DumpRenderTreeSupportEfl.cpp b/Source/WebKit/efl/WebCoreSupport/DumpRenderTreeSupportEfl.cpp index 1eb58d5b5..2a4a9fcc9 100644 --- a/Source/WebKit/efl/WebCoreSupport/DumpRenderTreeSupportEfl.cpp +++ b/Source/WebKit/efl/WebCoreSupport/DumpRenderTreeSupportEfl.cpp @@ -40,11 +40,6 @@ #include <workers/WorkerThread.h> #include <wtf/text/AtomicString.h> -#if ENABLE(SVG) -#include <SVGDocumentExtensions.h> -#include <SVGSMILElement.h> -#endif - unsigned DumpRenderTreeSupportEfl::activeAnimationsCount(const Evas_Object* ewkFrame) { WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame); @@ -174,30 +169,6 @@ bool DumpRenderTreeSupportEfl::pauseAnimation(Evas_Object* ewkFrame, const char* return frame->animation()->pauseAnimationAtTime(element->renderer(), name, time); } -bool DumpRenderTreeSupportEfl::pauseSVGAnimation(Evas_Object* ewkFrame, const char* animationId, const char* elementId, double time) -{ -#if ENABLE(SVG) - WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame); - - if (!frame) - return false; - - WebCore::Document* document = frame->document(); - - if (!document || !document->svgExtensions()) - return false; - - WebCore::Element* element = document->getElementById(animationId); - - if (!element || !WebCore::SVGSMILElement::isSMILElement(element)) - return false; - - return document->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<WebCore::SVGSMILElement*>(element), time); -#else - return false; -#endif -} - bool DumpRenderTreeSupportEfl::pauseTransition(Evas_Object* ewkFrame, const char* name, const char* elementId, double time) { WebCore::Frame* frame = EWKPrivate::coreFrame(ewkFrame); diff --git a/Source/WebKit/efl/WebCoreSupport/DumpRenderTreeSupportEfl.h b/Source/WebKit/efl/WebCoreSupport/DumpRenderTreeSupportEfl.h index 0ba342a6d..42af811d3 100644 --- a/Source/WebKit/efl/WebCoreSupport/DumpRenderTreeSupportEfl.h +++ b/Source/WebKit/efl/WebCoreSupport/DumpRenderTreeSupportEfl.h @@ -52,7 +52,6 @@ public: static int numberOfPages(const Evas_Object* ewkFrame, float pageWidth, float pageHeight); static int numberOfPagesForElementId(const Evas_Object* ewkFrame, const char* elementId, float pageWidth, float pageHeight); static bool pauseAnimation(Evas_Object* ewkFrame, const char* name, const char* elementId, double time); - static bool pauseSVGAnimation(Evas_Object* ewkFrame, const char* animationId, const char* elementId, double time); static bool pauseTransition(Evas_Object* ewkFrame, const char* name, const char* elementId, double time); static unsigned pendingUnloadEventCount(const Evas_Object* ewkFrame); static String renderTreeDump(Evas_Object* ewkFrame); diff --git a/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.cpp b/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.cpp index 78563ec7d..8224155a8 100644 --- a/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.cpp +++ b/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.cpp @@ -103,7 +103,7 @@ bool EditorClientEfl::shouldChangeSelectedRange(Range*, Range*, EAffinity, bool) return true; } -bool EditorClientEfl::shouldApplyStyle(CSSStyleDeclaration*, Range*) +bool EditorClientEfl::shouldApplyStyle(StylePropertySet*, Range*) { notImplemented(); return true; diff --git a/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.h b/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.h index 7ff181316..2b52e9dda 100644 --- a/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.h +++ b/Source/WebKit/efl/WebCoreSupport/EditorClientEfl.h @@ -73,7 +73,7 @@ public: virtual bool shouldInsertText(const String&, Range*, EditorInsertAction); virtual bool shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity, bool stillSelecting); - virtual bool shouldApplyStyle(CSSStyleDeclaration*, Range*); + virtual bool shouldApplyStyle(StylePropertySet*, Range*); virtual bool shouldMoveRangeAfterDelete(Range*, Range*); @@ -120,7 +120,7 @@ public: virtual void getGuessesForWord(const String& word, const String& context, WTF::Vector<String>& guesses); virtual void willSetInputMethodState(); virtual void setInputMethodState(bool enabled); - virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&) { } + virtual void requestCheckingOfString(WebCore::SpellChecker*, const WebCore::TextCheckingRequest&) { } virtual TextCheckerClient* textChecker() { return this; } private: diff --git a/Source/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.cpp b/Source/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.cpp index 1d4d64a9f..0096b8874 100644 --- a/Source/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.cpp +++ b/Source/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.cpp @@ -241,13 +241,9 @@ void FrameLoaderClientEfl::frameLoaderDestroyed() void FrameLoaderClientEfl::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long, const ResourceResponse& response) { -#if USE(SOUP) // Update our knowledge of request soup flags - some are only set // after the request is done. loader->request().setSoupMessageFlags(response.soupMessageFlags()); -#else - UNUSED_PARAM(loader); -#endif m_response = response; } @@ -951,7 +947,7 @@ void FrameLoaderClientEfl::dispatchDidBecomeFrameset(bool) PassRefPtr<FrameNetworkingContext> FrameLoaderClientEfl::createNetworkingContext() { - return FrameNetworkingContextEfl::create(EWKPrivate::coreFrame(m_frame)); + return FrameNetworkingContextEfl::create(EWKPrivate::coreFrame(m_frame), m_frame); } } diff --git a/Source/WebKit/efl/WebCoreSupport/FrameNetworkingContextEfl.cpp b/Source/WebKit/efl/WebCoreSupport/FrameNetworkingContextEfl.cpp new file mode 100644 index 000000000..8c20b213a --- /dev/null +++ b/Source/WebKit/efl/WebCoreSupport/FrameNetworkingContextEfl.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2010 Samsung Electronics + * Copyright (C) 2012 ProFUSION embedded systems + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. 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 "FrameNetworkingContextEfl.h" + +#include "ResourceHandle.h" +#include "ewk_frame.h" +#include "ewk_view.h" + +#include <Evas.h> + +namespace WebCore { + +PassRefPtr<FrameNetworkingContextEfl> FrameNetworkingContextEfl::create(Frame* frame, Evas_Object* ewkFrame) +{ + return adoptRef(new FrameNetworkingContextEfl(frame, ewkFrame)); +} + +FrameNetworkingContextEfl::FrameNetworkingContextEfl(Frame* frame, Evas_Object* ewkFrame) + : FrameNetworkingContext(frame) + , m_ewkFrame(ewkFrame) +{ +} + +SoupSession* FrameNetworkingContextEfl::soupSession() const +{ + return ewk_view_soup_session_get(ewk_frame_view_get(m_ewkFrame)); +} + +} diff --git a/Source/WebKit/efl/WebCoreSupport/FrameNetworkingContextEfl.h b/Source/WebKit/efl/WebCoreSupport/FrameNetworkingContextEfl.h index 4e67512d0..93ffd48bb 100644 --- a/Source/WebKit/efl/WebCoreSupport/FrameNetworkingContextEfl.h +++ b/Source/WebKit/efl/WebCoreSupport/FrameNetworkingContextEfl.h @@ -31,22 +31,21 @@ #include "FrameNetworkingContext.h" +typedef struct _Evas_Object Evas_Object; + namespace WebCore { class FrameNetworkingContextEfl : public WebCore::FrameNetworkingContext { public: - static PassRefPtr<FrameNetworkingContextEfl> create(WebCore::Frame* frame) - { - return adoptRef(new FrameNetworkingContextEfl(frame)); - } + static PassRefPtr<FrameNetworkingContextEfl> create(Frame*, Evas_Object*); WebCore::Frame* coreFrame() const { return frame(); } + virtual SoupSession* soupSession() const; private: - FrameNetworkingContextEfl(WebCore::Frame* frame) - : WebCore::FrameNetworkingContext(frame) - { - } + FrameNetworkingContextEfl(Frame*, Evas_Object*); + + Evas_Object* m_ewkFrame; }; } diff --git a/Source/WebKit/efl/WebCoreSupport/StorageTrackerClientEfl.cpp b/Source/WebKit/efl/WebCoreSupport/StorageTrackerClientEfl.cpp new file mode 100644 index 000000000..9d9d26918 --- /dev/null +++ b/Source/WebKit/efl/WebCoreSupport/StorageTrackerClientEfl.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 ProFUSION Embedded Systems + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "StorageTrackerClientEfl.h" + +#include "NotImplemented.h" + +namespace WebCore { + +void StorageTrackerClientEfl::dispatchDidModifyOrigin(const String&) +{ + notImplemented(); +} + +void StorageTrackerClientEfl::didFinishLoadingOrigins() +{ + notImplemented(); +} + +} diff --git a/Source/WebKit/efl/WebCoreSupport/StorageTrackerClientEfl.h b/Source/WebKit/efl/WebCoreSupport/StorageTrackerClientEfl.h new file mode 100644 index 000000000..62eae20ee --- /dev/null +++ b/Source/WebKit/efl/WebCoreSupport/StorageTrackerClientEfl.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 ProFUSION Embedded Systems + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef StorageTrackerClientEfl_h +#define StorageTrackerClientEfl_h + +#include "StorageTrackerClient.h" + +namespace WebCore { + +class StorageTrackerClientEfl : public StorageTrackerClient { +public: + virtual void dispatchDidModifyOrigin(const String&); + virtual void didFinishLoadingOrigins(); +}; + +} + +#endif // StorageTrackerClientEfl_h diff --git a/Source/WebKit/efl/WebCoreSupport/VibrationClientEfl.cpp b/Source/WebKit/efl/WebCoreSupport/VibrationClientEfl.cpp new file mode 100644 index 000000000..2365b72a3 --- /dev/null +++ b/Source/WebKit/efl/WebCoreSupport/VibrationClientEfl.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "VibrationClientEfl.h" + +#if ENABLE(VIBRATION) + +namespace WebCore { + +VibrationClientEfl::VibrationClientEfl(Evas_Object* view) + : m_view(view) +{ +} + +void VibrationClientEfl::vibrate(const unsigned long& time) +{ + evas_object_smart_callback_call(m_view, "vibration,vibrate", (void*)&time); +} + +void VibrationClientEfl::cancelVibration() +{ + evas_object_smart_callback_call(m_view, "vibration,cancel", 0); +} + +void VibrationClientEfl::vibrationDestroyed() +{ + delete this; +} + +} // namespace WebCore + +#endif // ENABLE(VIBRATION) + diff --git a/Source/WebKit/efl/WebCoreSupport/VibrationClientEfl.h b/Source/WebKit/efl/WebCoreSupport/VibrationClientEfl.h new file mode 100644 index 000000000..e7b0d925a --- /dev/null +++ b/Source/WebKit/efl/WebCoreSupport/VibrationClientEfl.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef VibrationClientEfl_h +#define VibrationClientEfl_h + +#include "VibrationClient.h" +#include <Evas.h> + +namespace WebCore { + +class VibrationClientEfl : public VibrationClient { +public: + VibrationClientEfl(Evas_Object* view); + virtual ~VibrationClientEfl() { } + + virtual void vibrate(const unsigned long& time); + virtual void cancelVibration(); + + virtual void vibrationDestroyed(); + +private: + Evas_Object* m_view; +}; + +} // namespace WebCore + +#endif // VibrationClientEfl_h + diff --git a/Source/WebKit/efl/ewebkit.pc.in b/Source/WebKit/efl/ewebkit.pc.in index 3a1c8f54f..dd6178347 100644 --- a/Source/WebKit/efl/ewebkit.pc.in +++ b/Source/WebKit/efl/ewebkit.pc.in @@ -7,7 +7,7 @@ datadir=${prefix}/share/@WebKit_LIBRARY_NAME@-@PROJECT_VERSION_MAJOR@ Name: WebKit-EFL Description: Web content engine for EFL applications Version: @PROJECT_VERSION@ -Requires: cairo evas ecore +Requires: cairo evas ecore libsoup-2.4 Libs: -L${libdir} -lewebkit @EXTRA_EWEBKIT_LINK@ Libs.private: @LIBS_PRIVATE@ Cflags: -I${includedir}/@WebKit_LIBRARY_NAME@-@PROJECT_VERSION_MAJOR@ diff --git a/Source/WebKit/efl/ewk/ewk_auth.cpp b/Source/WebKit/efl/ewk/ewk_auth.cpp index a4cb9e6b7..af2172ae1 100644 --- a/Source/WebKit/efl/ewk/ewk_auth.cpp +++ b/Source/WebKit/efl/ewk/ewk_auth.cpp @@ -20,20 +20,14 @@ #include "config.h" #include "ewk_auth.h" -#ifdef WTF_USE_SOUP #include "ewk_auth_soup.h" -#endif void ewk_auth_show_dialog_callback_set(Ewk_Auth_Show_Dialog_Callback callback) { -#if USE(SOUP) ewk_auth_soup_show_dialog_callback_set(callback); -#endif } void ewk_auth_credentials_set(char* username, char* password, void* data) { -#if USE(SOUP) ewk_auth_soup_credentials_set(username, password, data); -#endif } diff --git a/Source/WebKit/efl/ewk/ewk_cookies.cpp b/Source/WebKit/efl/ewk/ewk_cookies.cpp index 35e64ac40..7980c0120 100644 --- a/Source/WebKit/efl/ewk/ewk_cookies.cpp +++ b/Source/WebKit/efl/ewk/ewk_cookies.cpp @@ -21,20 +21,16 @@ #include "config.h" #include "ewk_cookies.h" +#include "CookieJarSoup.h" #include "ResourceHandle.h" #include <Eina.h> #include <eina_safety_checks.h> -#include <wtf/text/CString.h> - -#if USE(SOUP) -#include "CookieJarSoup.h" #include <glib.h> #include <libsoup/soup.h> -#endif +#include <wtf/text/CString.h> Eina_Bool ewk_cookies_file_set(const char* filename) { -#if USE(SOUP) SoupCookieJar* cookieJar = 0; if (filename) cookieJar = soup_cookie_jar_text_new(filename, FALSE); @@ -55,14 +51,10 @@ Eina_Bool ewk_cookies_file_set(const char* filename) soup_session_add_feature(session, SOUP_SESSION_FEATURE(cookieJar)); return true; -#else - return false; -#endif } void ewk_cookies_clear(void) { -#if USE(SOUP) GSList* list; GSList* p; SoupCookieJar* cookieJar = WebCore::defaultCookieJar(); @@ -72,13 +64,11 @@ void ewk_cookies_clear(void) soup_cookie_jar_delete_cookie(cookieJar, (SoupCookie*)p->data); soup_cookies_free(list); -#endif } Eina_List* ewk_cookies_get_all(void) { Eina_List* result = 0; -#if USE(SOUP) GSList* list; GSList* p; SoupCookieJar* cookieJar = WebCore::defaultCookieJar(); @@ -98,13 +88,12 @@ Eina_List* ewk_cookies_get_all(void) } soup_cookies_free(list); -#endif + return result; } void ewk_cookies_cookie_del(Ewk_Cookie* cookie) { -#if USE(SOUP) EINA_SAFETY_ON_NULL_RETURN(cookie); GSList* list; GSList* p; @@ -123,24 +112,20 @@ void ewk_cookies_cookie_del(Ewk_Cookie* cookie) soup_cookie_free(cookie1); soup_cookies_free(list); -#endif } void ewk_cookies_cookie_free(Ewk_Cookie* cookie) { -#if USE(SOUP) EINA_SAFETY_ON_NULL_RETURN(cookie); free(cookie->name); free(cookie->value); free(cookie->domain); free(cookie->path); free(cookie); -#endif } void ewk_cookies_policy_set(Ewk_Cookie_Policy cookiePolicy) { -#if USE(SOUP) SoupCookieJar* cookieJar = WebCore::defaultCookieJar(); SoupCookieJarAcceptPolicy policy; @@ -158,13 +143,11 @@ void ewk_cookies_policy_set(Ewk_Cookie_Policy cookiePolicy) } soup_cookie_jar_set_accept_policy(cookieJar, policy); -#endif } Ewk_Cookie_Policy ewk_cookies_policy_get(void) { Ewk_Cookie_Policy ewkPolicy = EWK_COOKIE_JAR_ACCEPT_ALWAYS; -#if USE(SOUP) SoupCookieJar* cookieJar = WebCore::defaultCookieJar(); SoupCookieJarAcceptPolicy policy; @@ -180,7 +163,6 @@ Ewk_Cookie_Policy ewk_cookies_policy_get(void) ewkPolicy = EWK_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY; break; } -#endif return ewkPolicy; } diff --git a/Source/WebKit/efl/ewk/ewk_cookies.h b/Source/WebKit/efl/ewk/ewk_cookies.h index 40e69d56c..29ac12182 100644 --- a/Source/WebKit/efl/ewk/ewk_cookies.h +++ b/Source/WebKit/efl/ewk/ewk_cookies.h @@ -21,6 +21,12 @@ /** * @file ewk_cookies.h * @brief The Ewk cookies API. + * + * @note If the libsoup network backend is being used the functions here will + * only work with the @b default SoupSession, which can be retrieved with + * ewk_network_defaul_soup_session_get(). If a different SoupSession is used + * and associated with a view with ewk_view_soup_session_set(), all cookie + * management will have to be done manually. */ #ifndef ewk_cookies_h diff --git a/Source/WebKit/efl/ewk/ewk_frame.cpp b/Source/WebKit/efl/ewk/ewk_frame.cpp index 8dc140150..29fe4f059 100644 --- a/Source/WebKit/efl/ewk/ewk_frame.cpp +++ b/Source/WebKit/efl/ewk/ewk_frame.cpp @@ -1606,7 +1606,6 @@ Eina_Bool ewk_frame_mixed_content_run_get(const Evas_Object* ewkFrame) Ewk_Certificate_Status ewk_frame_certificate_status_get(Evas_Object* ewkFrame) { -#if USE(SOUP) EWK_FRAME_SD_GET_OR_RETURN(ewkFrame, smartData, EWK_CERTIFICATE_STATUS_NO_CERTIFICATE); EINA_SAFETY_ON_NULL_RETURN_VAL(smartData->frame, EWK_CERTIFICATE_STATUS_NO_CERTIFICATE); @@ -1626,9 +1625,6 @@ Ewk_Certificate_Status ewk_frame_certificate_status_get(Evas_Object* ewkFrame) return EWK_CERTIFICATE_STATUS_TRUSTED; return EWK_CERTIFICATE_STATUS_UNTRUSTED; -#endif - - return EWK_CERTIFICATE_STATUS_NO_CERTIFICATE; } /** diff --git a/Source/WebKit/efl/ewk/ewk_main.cpp b/Source/WebKit/efl/ewk/ewk_main.cpp index cead2de72..7621d37d5 100644 --- a/Source/WebKit/efl/ewk/ewk_main.cpp +++ b/Source/WebKit/efl/ewk/ewk_main.cpp @@ -25,8 +25,12 @@ #include "Logging.h" #include "PageCache.h" #include "PageGroup.h" +#include "ResourceHandle.h" #include "ScriptController.h" #include "Settings.h" +#include "StorageTracker.h" +#include "StorageTrackerClientEfl.h" +#include "ewk_auth_soup.h" #include "ewk_logging.h" #include "ewk_network.h" #include "ewk_private.h" @@ -37,21 +41,12 @@ #include <Edje.h> #include <Eina.h> #include <Evas.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <wtf/Threading.h> - -#if ENABLE(GLIB_SUPPORT) #include <glib-object.h> #include <glib.h> -#endif - -#if USE(SOUP) -// REMOVE-ME: see todo below -#include "ResourceHandle.h" -#include "ewk_auth_soup.h" #include <libsoup/soup.h> -#endif +#include <stdlib.h> +#include <sys/stat.h> +#include <wtf/Threading.h> static int _ewkInitCount = 0; @@ -135,16 +130,20 @@ int ewk_shutdown(void) return 0; } +static WebCore::StorageTrackerClientEfl* trackerClient() +{ + DEFINE_STATIC_LOCAL(WebCore::StorageTrackerClientEfl, trackerClient, ()); + return &trackerClient; +} + Eina_Bool _ewk_init_body(void) { -#if ENABLE(GLIB_SUPPORT) g_type_init(); if (!ecore_main_loop_glib_integrate()) WRN("Ecore was not compiled with GLib support, some plugins will not " "work (ie: Adobe Flash)"); -#endif WebCore::ScriptController::initializeThreading(); WebCore::initializeLoggingChannelsIfNecessary(); @@ -174,17 +173,11 @@ Eina_Bool _ewk_init_body(void) ewk_network_tls_certificate_check_set(false); - // TODO: this should move to WebCore, already reported to webkit-gtk folks: -#if USE(SOUP) - if (1) { - SoupSession* session = WebCore::ResourceHandle::defaultSession(); - soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_SNIFFER); - soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_DECODER); + WebCore::StorageTracker::initializeTracker(webkitDirectory.utf8().data(), trackerClient()); - SoupSessionFeature* auth_dialog = static_cast<SoupSessionFeature*>(g_object_new(EWK_TYPE_SOUP_AUTH_DIALOG, 0)); - soup_session_add_feature(session, auth_dialog); - } -#endif + SoupSession* session = WebCore::ResourceHandle::defaultSession(); + SoupSessionFeature* auth_dialog = static_cast<SoupSessionFeature*>(g_object_new(EWK_TYPE_SOUP_AUTH_DIALOG, 0)); + soup_session_add_feature(session, auth_dialog); return true; } diff --git a/Source/WebKit/efl/ewk/ewk_network.cpp b/Source/WebKit/efl/ewk/ewk_network.cpp index 0ca5bd1bb..541ccddab 100644 --- a/Source/WebKit/efl/ewk/ewk_network.cpp +++ b/Source/WebKit/efl/ewk/ewk_network.cpp @@ -21,18 +21,14 @@ #include "ewk_network.h" #include "NetworkStateNotifier.h" +#include "ResourceHandle.h" #include "ewk_logging.h" #include <Eina.h> -#include <wtf/text/CString.h> - -#if USE(SOUP) -#include "ResourceHandle.h" #include <libsoup/soup.h> -#endif +#include <wtf/text/CString.h> void ewk_network_proxy_uri_set(const char* proxy) { -#if USE(SOUP) SoupSession* session = WebCore::ResourceHandle::defaultSession(); if (!proxy) { @@ -46,14 +42,10 @@ void ewk_network_proxy_uri_set(const char* proxy) g_object_set(session, SOUP_SESSION_PROXY_URI, uri, NULL); soup_uri_free(uri); -#elif USE(CURL) - EINA_SAFETY_ON_TRUE_RETURN(1); -#endif } const char* ewk_network_proxy_uri_get(void) { -#if USE(SOUP) SoupURI* uri; SoupSession* session = WebCore::ResourceHandle::defaultSession(); g_object_get(session, SOUP_SESSION_PROXY_URI, &uri, NULL); @@ -65,9 +57,6 @@ const char* ewk_network_proxy_uri_get(void) WTF::String proxy = soup_uri_to_string(uri, false); return eina_stringshare_add(proxy.utf8().data()); -#elif USE(CURL) - EINA_SAFETY_ON_TRUE_RETURN_VAL(1, 0); -#endif } void ewk_network_state_notifier_online_set(Eina_Bool online) @@ -79,47 +68,35 @@ Eina_Bool ewk_network_tls_certificate_check_get() { bool checkCertificates = false; -#if USE(SOUP) SoupSession* defaultSession = WebCore::ResourceHandle::defaultSession(); g_object_get(defaultSession, "ssl-strict", &checkCertificates, NULL); -#endif return checkCertificates; } void ewk_network_tls_certificate_check_set(Eina_Bool checkCertificates) { -#if USE(SOUP) SoupSession* defaultSession = WebCore::ResourceHandle::defaultSession(); g_object_set(defaultSession, "ssl-strict", checkCertificates, NULL); -#endif } const char* ewk_network_tls_ca_certificates_path_get() { const char* bundlePath = 0; -#if USE(SOUP) SoupSession* defaultSession = WebCore::ResourceHandle::defaultSession(); g_object_get(defaultSession, "ssl-ca-file", &bundlePath, NULL); -#endif return bundlePath; } void ewk_network_tls_ca_certificates_path_set(const char* bundlePath) { -#if USE(SOUP) SoupSession* defaultSession = WebCore::ResourceHandle::defaultSession(); g_object_set(defaultSession, "ssl-ca-file", bundlePath, NULL); -#endif } SoupSession* ewk_network_default_soup_session_get() { -#if USE(SOUP) return WebCore::ResourceHandle::defaultSession(); -#else - return 0; -#endif } diff --git a/Source/WebKit/efl/ewk/ewk_network.h b/Source/WebKit/efl/ewk/ewk_network.h index 3977e9978..dbec81584 100644 --- a/Source/WebKit/efl/ewk/ewk_network.h +++ b/Source/WebKit/efl/ewk/ewk_network.h @@ -26,17 +26,21 @@ #define ewk_network_h #include <Eina.h> +#include <libsoup/soup-session.h> #ifdef __cplusplus extern "C" { #endif -typedef struct _SoupSession SoupSession; - /** * Sets the given proxy URI to network backend. * * @param proxy URI to set + * + * @note If the libsoup backend is being used, this function has effect on + * the @b default SoupSession, returned by ewk_network_default_soup_session_get(). + * If a different SoupSession is used and passed to ewk_view_soup_session_set(), + * this function will not have any effect on it. */ EAPI void ewk_network_proxy_uri_set(const char *proxy); @@ -46,6 +50,11 @@ EAPI void ewk_network_proxy_uri_set(const char *proxy); * The returned string should be freed by eina_stringshare_del() after use. * * @return current proxy URI or @c 0 if it's not set + * + * @note If the libsoup backend is being used, this function has effect on + * the @b default SoupSession, returned by ewk_network_default_soup_session_get(). + * If a different SoupSession is used and passed to ewk_view_soup_session_set(), + * this function will not have any effect on it. */ EAPI const char *ewk_network_proxy_uri_get(void); @@ -62,6 +71,11 @@ EAPI void ewk_network_state_notifier_online_set(Eina_Bool online); * By default, HTTPS connections are performed regardless of the validity of the certificate provided. * * @sa ewk_network_tls_ca_certificates_path_set + * + * @note If the libsoup backend is being used, this function has effect on + * the @b default SoupSession, returned by ewk_network_default_soup_session_get(). + * If a different SoupSession is used and passed to ewk_view_soup_session_set(), + * this function will not have any effect on it. */ EAPI Eina_Bool ewk_network_tls_certificate_check_get(void); @@ -73,6 +87,11 @@ EAPI Eina_Bool ewk_network_tls_certificate_check_get(void); * @param enable Whether to check the provided certificates or not. * * @sa ewk_network_tls_ca_certificates_path_set + * + * @note If the libsoup backend is being used, this function has effect on + * the @b default SoupSession, returned by ewk_network_default_soup_session_get(). + * If a different SoupSession is used and passed to ewk_view_soup_session_set(), + * this function will not have any effect on it. */ EAPI void ewk_network_tls_certificate_check_set(Eina_Bool enable); @@ -89,6 +108,11 @@ EAPI void ewk_network_tls_certificate_check_set(Eina_Bool enable); * By default, the path is not set, so all certificates are considered as not signed by a trusted root CA. * * @sa ewk_network_tls_certificate_check_set + * + * @note If the libsoup backend is being used, this function has effect on + * the @b default SoupSession, returned by ewk_network_default_soup_session_get(). + * If a different SoupSession is used and passed to ewk_view_soup_session_set(), + * this function will not have any effect on it. */ EAPI const char *ewk_network_tls_ca_certificates_path_get(void); @@ -107,17 +131,18 @@ EAPI const char *ewk_network_tls_ca_certificates_path_get(void); * @param path The path to the certificate bundle. * * @sa ewk_network_tls_certificate_check_set + * + * @note If the libsoup backend is being used, this function has effect on + * the @b default SoupSession, returned by ewk_network_default_soup_session_get(). + * If a different SoupSession is used and passed to ewk_view_soup_session_set(), + * this function will not have any effect on it. */ EAPI void ewk_network_tls_ca_certificates_path_set(const char *path); /** * Returns the default @c SoupSession used by all views. * - * This function is meaningful only if WebKit has been compiled with the - * @c Soup network backend. - * - * @return The default @c SoupSession in use, or @c NULL if another network - * backend was used. + * @return The default @c SoupSession in use. */ EAPI SoupSession *ewk_network_default_soup_session_get(void); diff --git a/Source/WebKit/efl/ewk/ewk_settings.cpp b/Source/WebKit/efl/ewk/ewk_settings.cpp index af561c3b6..d13b39e7e 100644 --- a/Source/WebKit/efl/ewk/ewk_settings.cpp +++ b/Source/WebKit/efl/ewk/ewk_settings.cpp @@ -24,6 +24,7 @@ #include "ApplicationCacheStorage.h" #include "CrossOriginPreflightResultCache.h" #include "DatabaseTracker.h" +#include "StorageTracker.h" #include "FontCache.h" #include "FrameView.h" #include "IconDatabase.h" @@ -57,6 +58,7 @@ static const char* s_offlineAppCachePath = 0; static const char* _ewk_icon_database_path = 0; static const char* s_webDatabasePath = 0; +static const char* s_localStoragePath = 0; static uint64_t s_webDatabaseQuota = 1 * 1024 * 1024; // 1MB. static WTF::String _ewk_settings_webkit_platform_get() @@ -111,6 +113,30 @@ void ewk_settings_web_database_clear() #endif } +void ewk_settings_local_storage_path_set(const char* path) +{ + WebCore::StorageTracker::tracker().setDatabaseDirectoryPath(WTF::String::fromUTF8(path)); + eina_stringshare_replace(&s_localStoragePath, path); +} + +const char* ewk_settings_local_storage_path_get(void) +{ + return s_localStoragePath; +} + +void ewk_settings_local_storage_database_clear() +{ + WebCore::StorageTracker::tracker().deleteAllOrigins(); +} + +void ewk_settings_local_storage_database_origin_clear(const char* url) +{ + EINA_SAFETY_ON_NULL_RETURN(url); + + const WebCore::KURL kurl(WebCore::KURL(), WTF::String::fromUTF8(url)); + WebCore::StorageTracker::tracker().deleteOrigin(WebCore::SecurityOrigin::create(kurl).get()); +} + void ewk_settings_web_database_path_set(const char* path) { #if ENABLE(SQL_DATABASE) diff --git a/Source/WebKit/efl/ewk/ewk_settings.h b/Source/WebKit/efl/ewk/ewk_settings.h index 1e61b4402..cce9a5aa7 100644 --- a/Source/WebKit/efl/ewk/ewk_settings.h +++ b/Source/WebKit/efl/ewk/ewk_settings.h @@ -68,6 +68,53 @@ EAPI void ewk_settings_web_database_clear(void); EAPI void ewk_settings_web_database_path_set(const char *path); /** + * Sets the current path to the directory where WebKit will write the + * HTML5 local storage indexing database (the one keeping track of + * individual views' local storage databases). + * + * By default, the value is @c ~/.webkit + * + * @param path the new local storage database directory path + * + * @note You may want to call + * ewk_view_setting_local_storage_database_path_set() on the same @p + * path, here, for your views. + */ +EAPI void ewk_settings_local_storage_path_set(const char* path); + +/** + * Returns directory's path where the HTML5 local storage indexing + * database is stored. + * + * This is guaranteed to be eina-stringshared, so whenever possible + * save yourself some cpu cycles and use eina_stringshare_ref() + * instead of eina_stringshare_add() or strdup(). + * + * @return database path or @c NULL, on errors. + * + * @see ewk_settings_local_storage_path_set() + */ +EAPI const char* ewk_settings_local_storage_path_get(void); + +/** + * Removes @b all HTML 5 local storage databases. + */ +EAPI void ewk_settings_local_storage_database_clear(); + +/** + * Clears the HTML 5 local storage database for the given URL + * (origin). + * + * @param url which URL to clear local storage to. + * + * After this call, the file holding the local storage database for + * that origin will be deleted, along with its entry on the local + * storage files database (a file stored under the path returned by + * ewk_settings_local_storage_path_get()). + */ +EAPI void ewk_settings_local_storage_database_origin_clear(const char *url); + +/** * Returns directory path where web database is stored. * * By default, the value is @c ~/.webkit diff --git a/Source/WebKit/efl/ewk/ewk_view.cpp b/Source/WebKit/efl/ewk/ewk_view.cpp index 9789c1c30..8a9674022 100644 --- a/Source/WebKit/efl/ewk/ewk_view.cpp +++ b/Source/WebKit/efl/ewk/ewk_view.cpp @@ -1,6 +1,6 @@ /* Copyright (C) 2009-2010 ProFUSION embedded systems - Copyright (C) 2009-2011 Samsung Electronics + Copyright (C) 2009-2012 Samsung Electronics This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -50,6 +50,7 @@ #include "ProgressTracker.h" #include "RefPtrCairo.h" #include "RenderTheme.h" +#include "ResourceHandle.h" #include "Settings.h" #include "c_instance.h" #include "ewk_logging.h" @@ -59,6 +60,7 @@ #include <Evas.h> #include <eina_safety_checks.h> #include <inttypes.h> +#include <libsoup/soup-session.h> #include <limits> #include <math.h> #include <sys/time.h> @@ -68,6 +70,10 @@ #include "DeviceOrientationClientEfl.h" #endif +#if ENABLE(VIBRATION) +#include "VibrationClientEfl.h" +#endif + static const float zoomMinimum = 0.05; static const float zoomMaximum = 4.0; @@ -211,6 +217,7 @@ struct _Ewk_View_Private_Data { } center; Ecore_Animator* animator; } animatedZoom; + SoupSession* soupSession; }; #ifndef EWK_TYPE_CHECK @@ -604,15 +611,19 @@ static Ewk_View_Private_Data* _ewk_view_priv_new(Ewk_View_Smart_Data* smartData) pageClients.editorClient = new WebCore::EditorClientEfl(smartData->self); pageClients.dragClient = new WebCore::DragClientEfl; pageClients.inspectorClient = new WebCore::InspectorClientEfl; -#if ENABLE(DEVICE_ORIENTATION) - pageClients.deviceMotionClient = new WebCore::DeviceMotionClientEfl; - pageClients.deviceOrientationClient = new WebCore::DeviceOrientationClientEfl; -#endif priv->page = new WebCore::Page(pageClients); if (!priv->page) { CRITICAL("Could not create WebKit Page"); goto error_page; } +#if ENABLE(DEVICE_ORIENTATION) + WebCore::provideDeviceMotionTo(priv->page, new WebCore::DeviceMotionClientEfl); + WebCore::provideDeviceOrientationTo(priv->page, new WebCore::DeviceOrientationClientEfl); +#endif + +#if ENABLE(VIBRATION) + WebCore::provideVibrationTo(priv->page, new WebCore::VibrationClientEfl(smartData->self)); +#endif priv->pageSettings = priv->page->settings(); if (!priv->pageSettings) { @@ -714,6 +725,8 @@ static Ewk_View_Private_Data* _ewk_view_priv_new(Ewk_View_Smart_Data* smartData) goto error_history; } + priv->soupSession = WebCore::ResourceHandle::defaultSession(); + return priv; error_history: @@ -3913,6 +3926,25 @@ Ewk_Page_Visibility_State ewk_view_visibility_state_get(const Evas_Object* ewkVi #endif } +SoupSession* ewk_view_soup_session_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->soupSession; +} + +void ewk_view_soup_session_set(Evas_Object* ewkView, SoupSession* session) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); + EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv); + if (!SOUP_IS_SESSION_ASYNC(session)) { + ERR("WebKit requires an SoupSessionAsync to work properly, but " + "a SoupSessionSync was provided."); + return; + } + priv->soupSession = session; +} + namespace EWKPrivate { WebCore::Page *corePage(const Evas_Object *ewkView) diff --git a/Source/WebKit/efl/ewk/ewk_view.h b/Source/WebKit/efl/ewk/ewk_view.h index d3474a64b..7de0e462f 100644 --- a/Source/WebKit/efl/ewk/ewk_view.h +++ b/Source/WebKit/efl/ewk/ewk_view.h @@ -95,6 +95,7 @@ #include <Evas.h> #include <cairo.h> +#include <libsoup/soup-session.h> #ifdef __cplusplus extern "C" { @@ -2335,6 +2336,34 @@ EAPI Eina_Bool ewk_view_mixed_content_displayed_get(const Evas_Object *o); */ EAPI Eina_Bool ewk_view_mixed_content_run_get(const Evas_Object *o); +/** + * Returns the SoupSession associated with this view. + * + * By default, all views share the same, default soup session also available + * by calling ewk_network_default_soup_session_get. + * + * @param o The view to query. + * + * @sa ewk_view_soup_session_set, ewk_network_default_soup_session_get + */ +EAPI SoupSession* ewk_view_soup_session_get(const Evas_Object *o); + +/** + * Associates a new SoupSession with this view. + * + * Only sessions of type SoupSessionAsync are supported. + * + * @note Changing the SoupSession should not be needed in most cases. If + * a different SoupSession is used, the cookie management and some + * network functions in ewk will not have any effect on it. + * + * @param o The view to change. + * @param session The new SoupSession. + * + * @sa ewk_view_soup_session_get, ewk_network_default_soup_session_get + */ +EAPI void ewk_view_soup_session_set(Evas_Object *o, SoupSession *session); + #ifdef __cplusplus } #endif diff --git a/Source/WebKit/gtk/ChangeLog b/Source/WebKit/gtk/ChangeLog index 8c59bb93f..59bb90acb 100644 --- a/Source/WebKit/gtk/ChangeLog +++ b/Source/WebKit/gtk/ChangeLog @@ -1,3 +1,454 @@ +2012-02-24 Shinya Kawanaka <shinyak@chromium.org> + + SpellCheckRequest needs to know the context where the spellcheck happened. + https://bugs.webkit.org/show_bug.cgi?id=79320 + + Reviewed by Hajime Morita. + + * WebCoreSupport/TextCheckerClientGtk.h: + (WebKit::TextCheckerClientGtk::requestCheckingOfString): + +2012-02-23 ChangSeok Oh <shivamidow@gmail.com> + + [GTK] DRT doesn't support scheduleAsynchronousKeyDown. + https://bugs.webkit.org/show_bug.cgi?id=78481 + + Reviewed by Gustavo Noronha Silva. + + Added a new API to deliver all mutations explicitly. + + * WebCoreSupport/DumpRenderTreeSupportGtk.cpp: + (DumpRenderTreeSupportGtk::deliverAllMutationsIfNecessary): + * WebCoreSupport/DumpRenderTreeSupportGtk.h: + (DumpRenderTreeSupportGtk): + +2012-02-23 Philippe Normand <pnormand@igalia.com> + + [GTK] FullScreen signals + https://bugs.webkit.org/show_bug.cgi?id=76181 + + Reviewed by Martin Robinson. + + Added entering-fullscreen and leaving-fullscreen signals, meant to + be used by the user agent to be notified when an element requests + full screen display and when the full screen display is to be + disabled. + + * WebCoreSupport/ChromeClientGtk.cpp: + (WebKit::ChromeClient::supportsFullScreenForElement): + (WebKit::onFullscreenGtkKeyPressEvent): + (WebKit::ChromeClient::cancelFullScreen): + (WebKit::ChromeClient::enterFullScreenForElement): + (WebKit::ChromeClient::exitFullScreenForElement): + * WebCoreSupport/ChromeClientGtk.h: + * tests/testwebview.c: + * webkit/webkitwebview.cpp: + (webkit_web_view_real_entering_fullscreen): + (webkit_web_view_real_leaving_fullscreen): + (webkit_web_view_class_init): + * webkit/webkitwebview.h: + +2012-02-21 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/EditorClientGtk.cpp: + (WebKit::EditorClient::shouldApplyStyle): + * WebCoreSupport/EditorClientGtk.h: + (EditorClient): + +2012-02-22 Philippe Normand <pnormand@igalia.com> + + Unreviewed, rolling out r108522. + http://trac.webkit.org/changeset/108522 + https://bugs.webkit.org/show_bug.cgi?id=76181 + + Broke 4 fullscreen tests on GTK. + + * WebCoreSupport/ChromeClientGtk.cpp: + (WebKit::ChromeClient::supportsFullScreenForElement): + (WebKit::ChromeClient::enterFullScreenForElement): + (WebKit::ChromeClient::exitFullScreenForElement): + * WebCoreSupport/ChromeClientGtk.h: + (ChromeClient): + * tests/testwebview.c: + * webkit/webkitwebview.cpp: + (webkit_web_view_class_init): + * webkit/webkitwebview.h: + (_WebKitWebViewClass): + +2012-02-20 Philippe Normand <pnormand@igalia.com> + + [GTK] FullScreen signals + https://bugs.webkit.org/show_bug.cgi?id=76181 + + Reviewed by Martin Robinson. + + Added entering-fullscreen and leaving-fullscreen signals, meant to + be used by the user agent to be notified when an element requests + full screen display and when the full screen display is to be + disabled. + + * WebCoreSupport/ChromeClientGtk.cpp: + (WebKit::ChromeClient::supportsFullScreenForElement): + (WebKit::onFullscreenGtkKeyPressEvent): + (WebKit::ChromeClient::cancelFullScreen): + (WebKit::ChromeClient::enterFullScreenForElement): + (WebKit::ChromeClient::exitFullScreenForElement): + * WebCoreSupport/ChromeClientGtk.h: + * tests/testwebview.c: + * webkit/webkitwebview.cpp: + (webkit_web_view_real_entering_fullscreen): + (webkit_web_view_real_leaving_fullscreen): + (webkit_web_view_class_init): + * webkit/webkitwebview.h: + +2012-02-22 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/EditorClientGtk.cpp: + (WebKit::EditorClient::shouldApplyStyle): + * WebCoreSupport/EditorClientGtk.h: + (EditorClient): + +2012-02-22 Carlos Garcia Campos <cgarcia@igalia.com> + + Unreviewed, rolling out r107351. + http://trac.webkit.org/changeset/107351 + https://bugs.webkit.org/show_bug.cgi?id=53600 + + Several issues introduced in WebKitGTK+ API + + * WebCoreSupport/ChromeClientGtk.cpp: + (WebKit::ChromeClient::ChromeClient): + (WebKit::ChromeClient::chromeDestroyed): + (WebKit::ChromeClient::canRunModal): + (WebKit::ChromeClient::runModal): + * WebCoreSupport/ChromeClientGtk.h: + (ChromeClient): + * webkit/webkitwebview.cpp: + (webkit_web_view_class_init): + +2012-02-21 Philippe Normand <pnormand@igalia.com> + + Fix one more GTK+ unit test after r108278. + + Reviewed by Alejandro G. Castro. + + * tests/testkeyevents.c: + (map_event_cb): No longer grab focus here. + (setup_keyevent_test): Grabbing focus here seems to be late enough in the process. + +2012-02-20 Martin Robinson <mrobinson@igalia.com> + + Fix GTK+ unit tests after r108281. + + Reviewed by Alejandro G. Castro. + + * tests/testwebplugindatabase.c: + (test_webkit_web_plugin_database_get_plugins): Update the description used + in the test. + +2012-02-20 Martin Robinson <mrobinson@igalia.com> + + Fix GTK+ unit tests after r108278. + + Reviewed by Alejandro G. Castro. + + Now that WebCore is no longer stealing focus, we need to + adjust where we grab focus to ensure that it actually succeeds. + + * tests/testcopyandpaste.c: + (map_event_cb): No longer grab focus here. + (runPasteTestCallback): Grabbing focus here seems to be late enough in the process. + +2012-02-20 Martin Robinson <mrobinson@igalia.com> + + [GTK] Web content oftens steals focus from other widgets + https://bugs.webkit.org/show_bug.cgi?id=77791 + + Reviewed by Gustavo Noronha Silva. + + * tests/testwebview.c: Added a WebKit1 test to verify this behavior. + +2012-02-20 Gustavo Noronha Silva <gns@gnome.org> + + [GTK] Needs to claim being a more up-to-date Chrome + https://bugs.webkit.org/show_bug.cgi?id=79044 + + Reviewed by Martin Robinson. + + * webkit/webkitwebsettings.cpp: + (chromeUserAgent): update the version of Chrome we claim to be + to avoid warnings from sites such as Wordpress saying that our + browser is outdated. + +2012-02-19 Paweł Forysiuk <tuxator@o2.pl> + [GTK] Can't find webinspector and error page redirection on Windows + https://bugs.webkit.org/show_bug.cgi?id=51616 + + Use an abstraction for finding shared resources on Windows. + + Reviewed by Martin Robinson. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::dispatchDidFailLoad): + * WebCoreSupport/InspectorClientGtk.cpp: + (WebKit::InspectorClient::inspectorFilesPath): + +2012-02-19 Gustavo Noronha Silva <gns@gnome.org> + + Unreviewed. Remove gsettings schema from EXTRA_DIST. + + * GNUmakefile.am: + +2012-02-19 Gustavo Noronha Silva <gns@gnome.org> + + [GTK] Remove unused GSettings stuff + https://bugs.webkit.org/show_bug.cgi?id=78995 + + Reviewed by Martin Robinson. + + * GNUmakefile.am: remove GSettings-related stuff. + * WebCoreSupport/InspectorClientGtk.cpp: + (WebKit): Remove unused code. + * org.webkitgtk.gschema.xml.in: Removed. + * webkit/webkitwebinspector.cpp: + (webkit_web_inspector_execute_script): remove gsettings-related helper. + * webkit/webkitwebinspectorprivate.h: Ditto. + +2012-02-17 Gyuyoung Kim <gyuyoung.kim@samsung.com> + + [GTK] change the way of registering DeviceOrientation clients. + https://bugs.webkit.org/show_bug.cgi?id=78680 + + Reviewed by Gustavo Noronha Silva. + + Bug 78085 removed deviceOrientationClient and deviceMotionClient from PageClients. Instead, + DeviceOrientationClient and DeviceMotionClient should be registered by PageSupplement class. + Chromium, mac and qt ports are already changed by Bug 78085. + + * webkit/webkitwebview.cpp: + (webkit_web_view_init): + +2012-02-16 Martin Robinson <mrobinson@igalia.com> + + [GTK] [AC] Events can starve accelerated compositing updates + https://bugs.webkit.org/show_bug.cgi?id=78826 + + Reviewed by Gustavo Noronha Silva. + + Instead of using a WebCore timer, which can be starved by GdkEvents, + use a raw GLib timer with GDK_PRIORITY_EVENTS to drive AC updates. + This prevents dragging from blocking rendering. + + * WebCoreSupport/AcceleratedCompositingContext.h: + (AcceleratedCompositingContext): Store a GLib source tag instead of a WebCore timer. + * WebCoreSupport/AcceleratedCompositingContextClutter.cpp: + (WebKit::AcceleratedCompositingContext::AcceleratedCompositingContext): + (WebKit::AcceleratedCompositingContext::AcceleratedCompositingContext): + Remove the timer upon destruction. + (WebKit::syncLayersTimeoutCallback): Added this callback for the GLib timer. + (WebKit::AcceleratedCompositingContext::markForSync): Use a GLib timer. + (WebKit::AcceleratedCompositingContext::syncLayersTimeout): Ditto. + * WebCoreSupport/AcceleratedCompositingContextGL.cpp: + (WebKit::AcceleratedCompositingContext::AcceleratedCompositingContext): + (WebKit::AcceleratedCompositingContext::~AcceleratedCompositingContext): + Remove the timer upon destruction. + (WebKit::syncLayersTimeoutCallback): Added this callback for the GLib timer. + (WebKit::AcceleratedCompositingContext::markForSync): Use a GLib timer. + (WebKit::AcceleratedCompositingContext::syncLayersTimeout): Ditto. + +2012-02-16 Adam Barth <abarth@webkit.org> + + Attempt to fix the GTK build. + + * WebCoreSupport/GeolocationClientGtk.cpp: + (WebKit::GeolocationClient::requestPermission): + (WebKit::GeolocationClient::cancelPermissionRequest): + +2012-02-16 Sergio Villar Senin <svillar@igalia.com> + + [soup] Move important SoupSession feature initialization to WebCore + https://bugs.webkit.org/show_bug.cgi?id=68602 + + Reviewed by Martin Robinson. + + Moved content sniffer and decoder initialization from WebKit to + WebCore because network stuff will not work as expected without + them. + + No new tests required as we're just moving stuff from WebKit to + WebCore. + + * webkit/webkitglobals.cpp: + (webkitInit): + +2012-02-16 Philippe Normand <pnormand@igalia.com> + + Unreviewed, rolling out r107941. + http://trac.webkit.org/changeset/107941 + https://bugs.webkit.org/show_bug.cgi?id=68602 + + Broke 23 http tests on GTK + + * webkit/webkitglobals.cpp: + (webkitInit): + +2012-02-16 Sergio Villar Senin <svillar@igalia.com> + + [soup] Move important SoupSession feature initialization to WebCore + https://bugs.webkit.org/show_bug.cgi?id=68602 + + Reviewed by Martin Robinson. + + Moved content sniffer and decoder initialization from WebKit to + WebCore because network stuff will not work as expected without + them. + + No new tests required as we're just moving stuff from WebKit to + WebCore. + + * webkit/webkitglobals.cpp: + (webkitInit): + +2012-01-31 Raphael Kubo da Costa <kubo@profusion.mobi> + + [soup] Add support for multiple SoupSessions. + https://bugs.webkit.org/show_bug.cgi?id=77341 + + Reviewed by Gustavo Noronha Silva. + + Adapt to the changes to FrameNetworkingContext in WebCore. + + * GNUmakefile.am: + * WebCoreSupport/FrameNetworkingContextGtk.cpp: Copied from Source/WebKit/gtk/WebCoreSupport/FrameNetworkingContextGtk.h. + (WebKit): + (WebKit::FrameNetworkingContextGtk::soupSession): Always return ResourceHandle::defaultSession(). + * WebCoreSupport/FrameNetworkingContextGtk.h: + (FrameNetworkingContextGtk): + +2012-02-15 Sadrul Habib Chowdhury <sadrul@chromium.org> + + Notify ChromeClient when touch-event handlers are installed/removed. + https://bugs.webkit.org/show_bug.cgi?id=77440 + + Reviewed by Darin Fisher and Ryosuke Niwa. + + * WebCoreSupport/ChromeClientGtk.h: + (WebKit::ChromeClient::numTouchEventHandlersChanged): + +2012-02-15 No'am Rosenthal <noam.rosenthal@nokia.com> + + [Texmap] Divide TextureMapperNode.cpp to 3 files. + https://bugs.webkit.org/show_bug.cgi?id=76660 + + Rename TextureMapperNode to TextureMapperLayer. + + Reviewed by Kenneth Rohde Christiansen. + + * WebCoreSupport/AcceleratedCompositingContext.h: + (AcceleratedCompositingContext): + * WebCoreSupport/AcceleratedCompositingContextGL.cpp: + (WebKit::AcceleratedCompositingContext::AcceleratedCompositingContext): + (WebKit::AcceleratedCompositingContext::enabled): + (WebKit::AcceleratedCompositingContext::renderLayersToWindow): + (WebKit::AcceleratedCompositingContext::attachRootGraphicsLayer): + (WebKit::AcceleratedCompositingContext::syncLayersTimeout): + +2012-02-11 Nikolas Zimmermann <nzimmermann@rim.com> + + Convert svg/animations to use SMIL methods for driving the timeline + https://bugs.webkit.org/show_bug.cgi?id=78422 + + Reviewed by Dirk Schulze. + + Remove SVG animation sampling functionality provided for DRT, which no longer uses it. + Instead we switched the svg/animations tests to use SVGSVGElement.setCurrentTime. + + * WebCoreSupport/DumpRenderTreeSupportGtk.cpp: + * WebCoreSupport/DumpRenderTreeSupportGtk.h: + (DumpRenderTreeSupportGtk): + +2012-02-13 Mario Sanchez Prada <msanchez@igalia.com> + + [GTK] Add GSList to the list of GObject types in GOwnPtr + https://bugs.webkit.org/show_bug.cgi?id=78487 + + Reviewed by Philippe Normand. + + * WebCoreSupport/ChromeClientGtk.cpp: + (WebKit::ChromeClient::runOpenPanel): Use GOwnPtr<GSList> for the + list of filenames returned by gtk_file_chooser_get_filenames(). + +2012-02-09 Zan Dobersek <zandobersek@gmail.com> + + [GTK] Add DRT support for modal dialogs + https://bugs.webkit.org/show_bug.cgi?id=53600 + + Reviewed by Martin Robinson. + + Add support for running modal dialogs. + + A new signal is added to the WebKitWebView. When emitted, the web view + is requesting to be displayed as a modal dialog. If accepted, the + ChromeClient then establishes a loop that is run until the chrome is destroyed. + If denied, nothing is done. + + * WebCoreSupport/ChromeClientGtk.cpp: + (WebKit::ChromeClient::ChromeClient): + (WebKit::ChromeClient::chromeDestroyed): + (WebKit::ChromeClient::canRunModal): + (WebKit::ChromeClient::runModal): + * WebCoreSupport/ChromeClientGtk.h: + (ChromeClient): + * webkit/webkitwebview.cpp: + (webkit_web_view_class_init): + +2012-02-09 Zan Dobersek <zandobersek@gmail.com> + + [Gtk] security/set-form-autocomplete-attribute.html fails + https://bugs.webkit.org/show_bug.cgi?id=78261 + + Reviewed by Martin Robinson. + + Add a helper function to DumpRenderTreeSupportGtk, returning + whether or not an element does perform autocompletion. + + * WebCoreSupport/DumpRenderTreeSupportGtk.cpp: + (DumpRenderTreeSupportGtk::elementDoesAutoCompleteForElementWithId): + * WebCoreSupport/DumpRenderTreeSupportGtk.h: + (DumpRenderTreeSupportGtk): + +2012-02-09 Martin Robinson <mrobinson@igalia.com> + + Build fix for GTK+ 2.x after my previous commit. + + * webkit/webkitwebview.cpp: + (webkit_web_view_expose_event): The name of the event is expose_event and not expose. + +2012-02-08 Dan Vrátil <dvratil@redhat.com>, Milan Crha <mcrha@redhat.com> + + [GTK] Embedded GtkWidgets are not drawn + https://bugs.webkit.org/show_bug.cgi?id=63451 + + Insert plugin widgets to WebKitWebView container as it's children. + Chain up to parent in webkit_web_view_draw() to ensure the child widgets are drawn. + + Reviewed by Martin Robinson. + + * WebCoreSupport/FrameLoaderClientGtk.cpp: + (WebKit::FrameLoaderClient::createPlugin): + * webkit/webkitwebview.cpp: + (webkit_web_view_draw): + 2012-02-08 Mario Sanchez Prada <msanchez@igalia.com> [Gtk] atk_text_get_text_at_offset() fails to provide the correct line for list items whose text wraps diff --git a/Source/WebKit/gtk/GNUmakefile.am b/Source/WebKit/gtk/GNUmakefile.am index 38d2bb02a..069b5b0a5 100644 --- a/Source/WebKit/gtk/GNUmakefile.am +++ b/Source/WebKit/gtk/GNUmakefile.am @@ -204,6 +204,7 @@ webkitgtk_sources += \ Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h \ Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp \ Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h \ + Source/WebKit/gtk/WebCoreSupport/FrameNetworkingContextGtk.cpp \ Source/WebKit/gtk/WebCoreSupport/FrameNetworkingContextGtk.h \ Source/WebKit/gtk/WebCoreSupport/FullscreenVideoController.cpp \ Source/WebKit/gtk/WebCoreSupport/FullscreenVideoController.h \ @@ -384,10 +385,6 @@ $(GENSOURCES_WEBKIT)/webkitenumtypes.cpp: $(webkitgtk_h_api) $(WebKit)/GNUmakefi && cp xgen-gtc $@ \ && rm -f xgen-gtc -# GSettings -gsettings_SCHEMAS = $(top_builddir)/Source/WebKit/gtk/org.webkitgtk-@WEBKITGTK_API_VERSION@.gschema.xml -@GSETTINGS_RULES@ - EXTRA_DIST += \ $(WebKit)/ChangeLog \ $(WebKit)/NEWS \ @@ -400,8 +397,7 @@ EXTRA_DIST += \ $(WebKit)/po/* \ $(WebKit)/resources/* \ $(WebKit)/tests/resources/* \ - $(WebKit)/tests/test_utils.h \ - $(WebKit)/org.webkitgtk.gschema.xml.in + $(WebKit)/tests/test_utils.h # extra resource files resourcesdir = ${datadir}/webkitgtk-@WEBKITGTK_API_VERSION@/resources diff --git a/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContext.h b/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContext.h index 42a5f24b6..cad47495d 100644 --- a/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContext.h +++ b/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContext.h @@ -28,7 +28,7 @@ #include <wtf/PassOwnPtr.h> #if USE(TEXTURE_MAPPER_GL) -#include "TextureMapperNode.h" +#include "TextureMapperLayer.h" #include "WindowGLContext.h" #endif @@ -48,7 +48,7 @@ public: void attachRootGraphicsLayer(WebCore::GraphicsLayer*); void scheduleRootLayerRepaint(const WebCore::IntRect&); void markForSync(); - void syncLayersTimeout(WebCore::Timer<AcceleratedCompositingContext>*); + void syncLayersTimeout(); void syncLayersNow(); void resizeRootLayer(const WebCore::IntSize&); bool renderLayersToWindow(const WebCore::IntRect& clipRect); @@ -64,7 +64,7 @@ public: private: WebKitWebView* m_webView; OwnPtr<WebCore::GraphicsLayer> m_rootGraphicsLayer; - WebCore::Timer<AcceleratedCompositingContext> m_syncTimer; + unsigned int m_syncTimerCallbackId; #if USE(CLUTTER) GtkWidget* m_rootLayerEmbedder; @@ -72,7 +72,7 @@ private: void initializeIfNecessary(); bool m_initialized; - WebCore::TextureMapperNode* m_rootTextureMapperNode; + WebCore::TextureMapperLayer* m_rootTextureMapperLayer; OwnPtr<WebCore::WindowGLContext> m_context; OwnPtr<WebCore::TextureMapper> m_textureMapper; #endif diff --git a/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContextClutter.cpp b/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContextClutter.cpp index b52b409e5..2e95fc56e 100644 --- a/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContextClutter.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContextClutter.cpp @@ -36,13 +36,15 @@ namespace WebKit { AcceleratedCompositingContext::AcceleratedCompositingContext(WebKitWebView* webView) : m_webView(webView) , m_rootGraphicsLayer(0) - , m_syncTimer(this, &AcceleratedCompositingContext::syncLayersTimeout) + , m_syncTimerCallbackId(0) , m_rootLayerEmbedder(0) { } AcceleratedCompositingContext::~AcceleratedCompositingContext() { + if (m_syncTimerCallbackId) + g_source_remove(m_syncTimerCallbackId); } bool AcceleratedCompositingContext::enabled() @@ -109,14 +111,23 @@ void AcceleratedCompositingContext::resizeRootLayer(const IntSize& size) gtk_widget_size_allocate(GTK_WIDGET(m_webView->priv->rootLayerEmbedder), &allocation); } +static gboolean syncLayersTimeoutCallback(AcceleratedCompositingContext* context) +{ + context->syncLayersTimeout(); + return FALSE; +} + void AcceleratedCompositingContext::markForSync() { - if (m_syncTimer.isActive()) + if (m_syncTimerCallbackId) return; - m_syncTimer.startOneShot(0); + + // We use a GLib timer because otherwise GTK+ event handling during + // dragging can starve WebCore timers, which have a lower priority. + m_syncTimerCallbackId = g_timeout_add_full(GDK_PRIORITY_EVENTS, 0, reinterpret_cast<GSourceFunc>(syncLayersTimeoutCallback), this, 0); } -void AcceleratedCompositingContext::syncLayersTimeout(Timer<AcceleratedCompositingContext>*) +void AcceleratedCompositingContext::syncLayersTimeout() { core(m_webView)->mainFrame()->view()->syncCompositingStateIncludingSubframes(); } diff --git a/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContextGL.cpp b/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContextGL.cpp index 9bfa3d0fe..8c4300f27 100644 --- a/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContextGL.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/AcceleratedCompositingContextGL.cpp @@ -28,7 +28,7 @@ #include "FrameView.h" #include "PlatformContextCairo.h" #include "TextureMapperGL.h" -#include "TextureMapperNode.h" +#include "TextureMapperLayer.h" #include "webkitwebviewprivate.h" #include <GL/gl.h> #include <cairo.h> @@ -41,15 +41,16 @@ namespace WebKit { AcceleratedCompositingContext::AcceleratedCompositingContext(WebKitWebView* webView) : m_webView(webView) - , m_syncTimer(this, &AcceleratedCompositingContext::syncLayersTimeout) + , m_syncTimerCallbackId(0) , m_initialized(false) - , m_rootTextureMapperNode(0) + , m_rootTextureMapperLayer(0) { } AcceleratedCompositingContext::~AcceleratedCompositingContext() { - + if (m_syncTimerCallbackId) + g_source_remove(m_syncTimerCallbackId); } void AcceleratedCompositingContext::initializeIfNecessary() @@ -69,7 +70,7 @@ void AcceleratedCompositingContext::initializeIfNecessary() bool AcceleratedCompositingContext::enabled() { - return m_rootTextureMapperNode && m_textureMapper; + return m_rootTextureMapperLayer && m_textureMapper; } @@ -90,7 +91,7 @@ bool AcceleratedCompositingContext::renderLayersToWindow(const IntRect& clipRect glViewport(0, 0, allocation.width, allocation.height); m_textureMapper->beginPainting(); - m_rootTextureMapperNode->paint(); + m_rootTextureMapperLayer->paint(); m_textureMapper->endPainting(); m_context->finishDrawing(); @@ -101,12 +102,12 @@ void AcceleratedCompositingContext::attachRootGraphicsLayer(GraphicsLayer* graph { if (!graphicsLayer) { m_rootGraphicsLayer.clear(); - m_rootTextureMapperNode = 0; + m_rootTextureMapperLayer = 0; return; } m_rootGraphicsLayer = GraphicsLayer::create(this); - m_rootTextureMapperNode = toTextureMapperNode(m_rootGraphicsLayer.get()); + m_rootTextureMapperLayer = toTextureMapperLayer(m_rootGraphicsLayer.get()); m_rootGraphicsLayer->addChild(graphicsLayer); m_rootGraphicsLayer->setDrawsContent(true); m_rootGraphicsLayer->setMasksToBounds(false); @@ -127,7 +128,7 @@ void AcceleratedCompositingContext::attachRootGraphicsLayer(GraphicsLayer* graph glViewport(0, 0, allocation.width, allocation.height); m_textureMapper = TextureMapperGL::create(); - m_rootTextureMapperNode->setTextureMapper(m_textureMapper.get()); + m_rootTextureMapperLayer->setTextureMapper(m_textureMapper.get()); m_rootGraphicsLayer->syncCompositingStateForThisLayerOnly(); } @@ -150,11 +151,20 @@ void AcceleratedCompositingContext::resizeRootLayer(const IntSize& size) m_rootGraphicsLayer->setNeedsDisplay(); } +static gboolean syncLayersTimeoutCallback(AcceleratedCompositingContext* context) +{ + context->syncLayersTimeout(); + return FALSE; +} + void AcceleratedCompositingContext::markForSync() { - if (m_syncTimer.isActive()) + if (m_syncTimerCallbackId) return; - m_syncTimer.startOneShot(0); + + // We use a GLib timer because otherwise GTK+ event handling during + // dragging can starve WebCore timers, which have a lower priority. + m_syncTimerCallbackId = g_timeout_add_full(GDK_PRIORITY_EVENTS, 0, reinterpret_cast<GSourceFunc>(syncLayersTimeoutCallback), this, 0); } void AcceleratedCompositingContext::syncLayersNow() @@ -165,16 +175,17 @@ void AcceleratedCompositingContext::syncLayersNow() core(m_webView)->mainFrame()->view()->syncCompositingStateIncludingSubframes(); } -void AcceleratedCompositingContext::syncLayersTimeout(Timer<AcceleratedCompositingContext>*) +void AcceleratedCompositingContext::syncLayersTimeout() { + m_syncTimerCallbackId = 0; syncLayersNow(); if (!m_rootGraphicsLayer) return; renderLayersToWindow(IntRect()); - if (toTextureMapperNode(m_rootGraphicsLayer.get())->descendantsOrSelfHaveRunningAnimations()) - m_syncTimer.startOneShot(1.0 / 60.0); + if (toTextureMapperLayer(m_rootGraphicsLayer.get())->descendantsOrSelfHaveRunningAnimations()) + m_syncTimerCallbackId = g_timeout_add_full(GDK_PRIORITY_EVENTS, 1000.0 / 60.0, reinterpret_cast<GSourceFunc>(syncLayersTimeoutCallback), this, 0); } void AcceleratedCompositingContext::notifyAnimationStarted(const WebCore::GraphicsLayer*, double time) diff --git a/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp index 955c166a9..d282f290a 100644 --- a/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp @@ -51,6 +51,8 @@ #include "RefPtrCairo.h" #include "SearchPopupMenuGtk.h" #include "SecurityOrigin.h" +#include "WebKitDOMBinding.h" +#include "WebKitDOMHTMLElementPrivate.h" #include "WindowFeatures.h" #include "webkitgeolocationpolicydecision.h" #include "webkitgeolocationpolicydecisionprivate.h" @@ -61,6 +63,8 @@ #include "webkitwebview.h" #include "webkitwebviewprivate.h" #include "webkitwebwindowfeaturesprivate.h" +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h> #include <glib.h> #include <glib/gi18n-lib.h> #include <gtk/gtk.h> @@ -807,15 +811,14 @@ void ChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser) if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { if (gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(dialog))) { - GSList* filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); + GOwnPtr<GSList> filenames(gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog))); Vector<String> names; - for (GSList* item = filenames ; item ; item = item->next) { + for (GSList* item = filenames.get() ; item ; item = item->next) { if (!item->data) continue; names.append(filenameToString(static_cast<char*>(item->data))); g_free(item->data); } - g_slist_free(filenames); chooser->chooseFiles(names); } else { gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); @@ -922,29 +925,69 @@ void ChromeClient::exitFullscreenForNode(Node* node) #if ENABLE(FULLSCREEN_API) bool ChromeClient::supportsFullScreenForElement(const WebCore::Element* element, bool withKeyboard) { - return true; + return !withKeyboard; +} + +static gboolean onFullscreenGtkKeyPressEvent(GtkWidget* widget, GdkEventKey* event, ChromeClient* chromeClient) +{ + switch (event->keyval) { + case GDK_KEY_Escape: + case GDK_KEY_f: + case GDK_KEY_F: + chromeClient->cancelFullScreen(); + return TRUE; + default: + break; + } + + return FALSE; +} + +void ChromeClient::cancelFullScreen() +{ + ASSERT(m_fullScreenElement); + m_fullScreenElement->document()->webkitCancelFullScreen(); } void ChromeClient::enterFullScreenForElement(WebCore::Element* element) { + gboolean returnValue; + GRefPtr<WebKitDOMHTMLElement> kitElement(adoptGRef(kit(reinterpret_cast<HTMLElement*>(element)))); + g_signal_emit_by_name(m_webView, "entering-fullscreen", kitElement.get(), &returnValue); + if (returnValue) + return; + + GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView)); + if (!widgetIsOnscreenToplevelWindow(window)) + return; + + g_signal_connect(window, "key-press-event", G_CALLBACK(onFullscreenGtkKeyPressEvent), this); + + m_fullScreenElement = element; + element->document()->webkitWillEnterFullScreenForElement(element); m_adjustmentWatcher.disableAllScrollbars(); -#if ENABLE(VIDEO) - if (element->tagName() == "VIDEO") - enterFullscreenForNode(static_cast<Node*>(element)); -#endif + gtk_window_fullscreen(GTK_WINDOW(window)); element->document()->webkitDidEnterFullScreenForElement(element); } void ChromeClient::exitFullScreenForElement(WebCore::Element* element) { + gboolean returnValue; + GRefPtr<WebKitDOMHTMLElement> kitElement(adoptGRef(kit(reinterpret_cast<HTMLElement*>(element)))); + g_signal_emit_by_name(m_webView, "leaving-fullscreen", kitElement.get(), &returnValue); + if (returnValue) + return; + + GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView)); + ASSERT(widgetIsOnscreenToplevelWindow(window)); + g_signal_handlers_disconnect_by_func(window, reinterpret_cast<void*>(onFullscreenGtkKeyPressEvent), this); + element->document()->webkitWillExitFullScreenForElement(element); + gtk_window_unfullscreen(GTK_WINDOW(window)); m_adjustmentWatcher.enableAllScrollbars(); -#if ENABLE(VIDEO) - if (element->tagName() == "VIDEO") - webViewExitFullscreen(m_webView); -#endif element->document()->webkitDidExitFullScreenForElement(element); + m_fullScreenElement.clear(); } #endif diff --git a/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h b/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h index 8c7c89233..5905f5679 100644 --- a/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h +++ b/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h @@ -155,10 +155,12 @@ namespace WebKit { virtual bool supportsFullScreenForElement(const Element*, bool withKeyboard); virtual void enterFullScreenForElement(Element*); virtual void exitFullScreenForElement(Element*); + void cancelFullScreen(); #endif virtual bool shouldRubberBandInDirection(ScrollDirection) const { return true; } virtual void numWheelEventHandlersChanged(unsigned) { } + virtual void numTouchEventHandlersChanged(unsigned) { } #if USE(ACCELERATED_COMPOSITING) virtual void attachRootGraphicsLayer(Frame*, GraphicsLayer*); @@ -185,6 +187,9 @@ namespace WebKit { unsigned int m_repaintSoonSourceId; void invalidateWidgetRect(const IntRect&); +#if ENABLE(FULLSCREEN_API) + RefPtr<Element> m_fullScreenElement; +#endif }; } diff --git a/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp index c59e1f792..8e6e26b14 100644 --- a/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp @@ -61,6 +61,7 @@ #include "TextIterator.h" #include "WebKitAccessibleWrapperAtk.h" #include "WebKitDOMRangePrivate.h" +#include "WebKitMutationObserver.h" #include "WorkerThread.h" #include "webkitglobalsprivate.h" #include "webkitwebframe.h" @@ -69,11 +70,6 @@ #include "webkitwebviewprivate.h" #include <JavaScriptCore/APICast.h> -#if ENABLE(SVG) -#include "SVGDocumentExtensions.h" -#include "SVGSMILElement.h" -#endif - using namespace JSC; using namespace WebCore; using namespace WebKit; @@ -395,22 +391,6 @@ bool DumpRenderTreeSupportGtk::pauseTransition(WebKitWebFrame* frame, const char return core(frame)->animation()->pauseTransitionAtTime(coreElement->renderer(), AtomicString(name), time); } -bool DumpRenderTreeSupportGtk::pauseSVGAnimation(WebKitWebFrame* frame, const char* animationId, double time, const char* elementId) -{ - ASSERT(core(frame)); -#if ENABLE(SVG) - Document* document = core(frame)->document(); - if (!document || !document->svgExtensions()) - return false; - Element* coreElement = document->getElementById(AtomicString(animationId)); - if (!coreElement || !SVGSMILElement::isSMILElement(coreElement)) - return false; - return document->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreElement), time); -#else - return false; -#endif -} - CString DumpRenderTreeSupportGtk::markerTextForListItem(WebKitWebFrame* frame, JSContextRef context, JSValueRef nodeObject) { JSC::ExecState* exec = toJS(context); @@ -913,3 +893,33 @@ void DumpRenderTreeSupportGtk::setHixie76WebSocketProtocolEnabled(WebKitWebView* UNUSED_PARAM(enabled); #endif } + +bool DumpRenderTreeSupportGtk::elementDoesAutoCompleteForElementWithId(WebKitWebFrame* frame, JSStringRef id) +{ + Frame* coreFrame = core(frame); + if (!coreFrame) + return false; + + Document* document = coreFrame->document(); + ASSERT(document); + + size_t bufferSize = JSStringGetMaximumUTF8CStringSize(id); + GOwnPtr<gchar> idBuffer(static_cast<gchar*>(g_malloc(bufferSize))); + JSStringGetUTF8CString(id, idBuffer.get(), bufferSize); + Node* coreNode = document->getElementById(String::fromUTF8(idBuffer.get())); + if (!coreNode || !coreNode->renderer()) + return false; + + HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(coreNode); + if (!inputElement) + return false; + + return inputElement->isTextField() && !inputElement->isPasswordField() && inputElement->shouldAutocomplete(); +} + +void DumpRenderTreeSupportGtk::deliverAllMutationsIfNecessary() +{ +#if ENABLE(MUTATION_OBSERVERS) + WebKitMutationObserver::deliverAllMutations(); +#endif +} diff --git a/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h b/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h index 06d30070a..02b80c476 100644 --- a/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h +++ b/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h @@ -75,7 +75,6 @@ public: static guint getPendingUnloadEventCount(WebKitWebFrame*); static bool pauseAnimation(WebKitWebFrame*, const char* name, double time, const char* element); static bool pauseTransition(WebKitWebFrame*, const char* name, double time, const char* element); - static bool pauseSVGAnimation(WebKitWebFrame*, const char* animationId, double time, const char* elementId); static WTF::CString markerTextForListItem(WebKitWebFrame*, JSContextRef, JSValueRef nodeObject); static unsigned int numberOfActiveAnimations(WebKitWebFrame*); static void suspendAnimations(WebKitWebFrame*); @@ -87,6 +86,7 @@ public: static void setAutofilled(JSContextRef, JSValueRef, bool); static void setValueForUser(JSContextRef, JSValueRef, JSStringRef); static bool shouldClose(WebKitWebFrame*); + static bool elementDoesAutoCompleteForElementWithId(WebKitWebFrame*, JSStringRef); // WebKitWebView static void executeCoreCommandByName(WebKitWebView*, const gchar* name, const gchar* value); @@ -129,6 +129,8 @@ public: static void setHixie76WebSocketProtocolEnabled(WebKitWebView*, bool enabled); + static void deliverAllMutationsIfNecessary(); + private: static bool s_drtRun; static bool s_linksIncludedInTabChain; diff --git a/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp index 913b0df8e..b8e160e28 100644 --- a/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp @@ -235,10 +235,10 @@ bool EditorClient::shouldChangeSelectedRange(Range* fromRange, Range* toRange, E return accept; } -bool EditorClient::shouldApplyStyle(WebCore::CSSStyleDeclaration* declaration, WebCore::Range* range) +bool EditorClient::shouldApplyStyle(WebCore::StylePropertySet* set, WebCore::Range* range) { gboolean accept = TRUE; - GRefPtr<WebKitDOMCSSStyleDeclaration> kitDeclaration(kit(declaration)); + GRefPtr<WebKitDOMCSSStyleDeclaration> kitDeclaration(kit(set->ensureCSSStyleDeclaration())); GRefPtr<WebKitDOMRange> kitRange(adoptGRef(kit(range))); g_signal_emit_by_name(m_webView, "should-apply-style", kitDeclaration.get(), kitRange.get(), &accept); return accept; diff --git a/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h b/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h index 2533c1644..ef159c646 100644 --- a/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h +++ b/Source/WebKit/gtk/WebCoreSupport/EditorClientGtk.h @@ -94,7 +94,7 @@ class EditorClient : public WebCore::EditorClient { virtual bool shouldInsertText(const WTF::String&, WebCore::Range*, WebCore::EditorInsertAction); virtual bool shouldChangeSelectedRange(WebCore::Range* fromRange, WebCore::Range* toRange, WebCore::EAffinity, bool stillSelecting); - virtual bool shouldApplyStyle(WebCore::CSSStyleDeclaration*, WebCore::Range*); + virtual bool shouldApplyStyle(WebCore::StylePropertySet*, WebCore::Range*); virtual bool shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*); diff --git a/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp index 60b00e893..42a494583 100644 --- a/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp @@ -33,6 +33,7 @@ #include "DocumentLoader.h" #include "DocumentLoaderGtk.h" #include "ErrorsGtk.h" +#include "FileSystem.h" #include "FormState.h" #include "FrameLoader.h" #include "FrameNetworkingContextGtk.h" @@ -482,8 +483,10 @@ PassRefPtr<Widget> FrameLoaderClient::createPlugin(const IntSize& pluginSize, HT GtkWidget* gtkWidget = 0; g_signal_emit_by_name(getViewFromFrame(m_frame), "create-plugin-widget", mimeTypeString.data(), urlString.data(), hash.get(), >kWidget); - if (gtkWidget) + if (gtkWidget) { + gtk_container_add(GTK_CONTAINER(getViewFromFrame(m_frame)), gtkWidget); return adoptRef(new GtkPluginWidget(gtkWidget)); + } RefPtr<PluginView> pluginView = PluginView::create(core(m_frame), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually); @@ -1103,7 +1106,9 @@ void FrameLoaderClient::dispatchDidFailLoad(const ResourceError& error) String content; gchar* fileContent = 0; - gchar* errorURI = g_filename_to_uri(DATA_DIR"/webkit-1.0/resources/error.html", NULL, NULL); + GOwnPtr<gchar> errorPath(g_build_filename(sharedResourcesPath().data(), "resources", "error.html", NULL)); + gchar* errorURI = g_filename_to_uri(errorPath.get(), 0, 0); + GFile* errorFile = g_file_new_for_uri(errorURI); g_free(errorURI); diff --git a/Source/WebKit/gtk/WebCoreSupport/FrameNetworkingContextGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/FrameNetworkingContextGtk.cpp new file mode 100644 index 000000000..4b9d12491 --- /dev/null +++ b/Source/WebKit/gtk/WebCoreSupport/FrameNetworkingContextGtk.cpp @@ -0,0 +1,35 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2012 ProFUSION embedded systems + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "FrameNetworkingContextGtk.h" + +#include "ResourceHandle.h" + +using namespace WebCore; + +namespace WebKit { + +SoupSession* FrameNetworkingContextGtk::soupSession() const +{ + return ResourceHandle::defaultSession(); +} + +} diff --git a/Source/WebKit/gtk/WebCoreSupport/FrameNetworkingContextGtk.h b/Source/WebKit/gtk/WebCoreSupport/FrameNetworkingContextGtk.h index 8e4c2148d..a59a94099 100644 --- a/Source/WebKit/gtk/WebCoreSupport/FrameNetworkingContextGtk.h +++ b/Source/WebKit/gtk/WebCoreSupport/FrameNetworkingContextGtk.h @@ -32,6 +32,7 @@ public: } WebCore::Frame* coreFrame() const { return frame(); } + virtual SoupSession* soupSession() const; private: FrameNetworkingContextGtk(WebCore::Frame* frame) diff --git a/Source/WebKit/gtk/WebCoreSupport/GeolocationClientGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/GeolocationClientGtk.cpp index fac1d73af..06e9fbd3f 100644 --- a/Source/WebKit/gtk/WebCoreSupport/GeolocationClientGtk.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/GeolocationClientGtk.cpp @@ -24,6 +24,7 @@ #if ENABLE(CLIENT_BASED_GEOLOCATION) #include "Chrome.h" +#include "ChromeClient.h" #include "Geolocation.h" #include "GeolocationController.h" #include "GeolocationError.h" @@ -137,12 +138,12 @@ WebCore::GeolocationPosition* GeolocationClient::lastPosition() void GeolocationClient::requestPermission(WebCore::Geolocation* geolocation) { - core(m_webView)->chrome()->requestGeolocationPermissionForFrame(geolocation->frame(), geolocation); + core(m_webView)->chrome()->client()->requestGeolocationPermissionForFrame(geolocation->frame(), geolocation); } void GeolocationClient::cancelPermissionRequest(WebCore::Geolocation* geolocation) { - core(m_webView)->chrome()->cancelGeolocationPermissionRequestForFrame(geolocation->frame(), geolocation); + core(m_webView)->chrome()->client()->cancelGeolocationPermissionRequestForFrame(geolocation->frame(), geolocation); } void GeolocationClient::positionChanged(GeocluePosition*, GeocluePositionFields fields, int timestamp, double latitude, double longitude, double altitude, GeoclueAccuracy* accuracy) diff --git a/Source/WebKit/gtk/WebCoreSupport/InspectorClientGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/InspectorClientGtk.cpp index d4d321d93..c1dd9b911 100644 --- a/Source/WebKit/gtk/WebCoreSupport/InspectorClientGtk.cpp +++ b/Source/WebKit/gtk/WebCoreSupport/InspectorClientGtk.cpp @@ -20,6 +20,7 @@ #include "config.h" #include "InspectorClientGtk.h" +#include "FileSystem.h" #include "Frame.h" #include "InspectorController.h" #include "NotImplemented.h" @@ -48,55 +49,16 @@ public: virtual ~InspectorFrontendSettingsGtk() { } private: -#ifdef HAVE_GSETTINGS - static bool shouldIgnoreSetting(const String& key) - { - // GSettings considers trying to fetch or set a setting that is - // not backed by a schema as programmer error, and aborts the - // program's execution. We check here to avoid having an unhandled - // setting as a fatal error. - LOG_VERBOSE(NotYetImplemented, "Unknown key ignored: %s", key.ascii().data()); - return true; - } - virtual String getProperty(const String& name) { - if (shouldIgnoreSetting(name)) - return String(); - - GSettings* settings = inspectorGSettings(); - if (!settings) - return String(); - - GRefPtr<GVariant> variant = adoptGRef(g_settings_get_value(settings, name.utf8().data())); - return String(g_variant_get_string(variant.get(), 0)); - } - - virtual void setProperty(const String& name, const String& value) - { - // Avoid setting unknown keys to avoid aborting the execution. - if (shouldIgnoreSetting(name)) - return; - - GSettings* settings = inspectorGSettings(); - if (!settings) - return; - - GRefPtr<GVariant> variant = adoptGRef(g_variant_new_string(value.utf8().data())); - g_settings_set_value(settings, name.utf8().data(), variant.get()); - } -#else - virtual String getProperty(const String&) - { notImplemented(); return String(); } - virtual void setProperty(const String&, const String&) + virtual void setProperty(const String& name, const String& value) { notImplemented(); } -#endif // HAVE_GSETTINGS }; } // namespace @@ -202,7 +164,7 @@ const char* InspectorClient::inspectorFilesPath() if (environmentPath && g_file_test(environmentPath, G_FILE_TEST_IS_DIR)) m_inspectorFilesPath.set(g_strdup(environmentPath)); else - m_inspectorFilesPath.set(g_build_filename(DATA_DIR, "webkitgtk-"WEBKITGTK_API_VERSION_STRING, "webinspector", NULL)); + m_inspectorFilesPath.set(g_build_filename(sharedResourcesPath().data(), "webinspector", NULL)); return m_inspectorFilesPath.get(); } diff --git a/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientGtk.h b/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientGtk.h index e5390bcc9..b3fa04994 100644 --- a/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientGtk.h +++ b/Source/WebKit/gtk/WebCoreSupport/TextCheckerClientGtk.h @@ -48,7 +48,7 @@ class TextCheckerClientGtk : public WebCore::TextCheckerClient { virtual WTF::String getAutoCorrectSuggestionForMisspelledWord(const WTF::String&); virtual void checkGrammarOfString(const UChar*, int length, WTF::Vector<WebCore::GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength); virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses); - virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&) {} + virtual void requestCheckingOfString(WebCore::SpellChecker*, const WebCore::TextCheckingRequest&) { } void updateSpellCheckingLanguage(const char*); private: diff --git a/Source/WebKit/gtk/org.webkitgtk.gschema.xml.in b/Source/WebKit/gtk/org.webkitgtk.gschema.xml.in deleted file mode 100644 index 17063f4b8..000000000 --- a/Source/WebKit/gtk/org.webkitgtk.gschema.xml.in +++ /dev/null @@ -1,32 +0,0 @@ -<schemalist> - <schema id="org.webkitgtk-@WEBKITGTK_API_VERSION@" path="/system/webkitgtk/"> - <child schema="org.webkitgtk-@WEBKITGTK_API_VERSION@.inspector" name="inspector"/> - </schema> - <schema id="org.webkitgtk-@WEBKITGTK_API_VERSION@.inspector" path="/system/webkitgtk/inspector/"> - <key name="resource-tracking-enabled" type="b"> - <default>false</default> - <summary>Resource Tracking Enabled</summary> - <description>Whether the Resource Tracking panel is always enabled.</description> - </key> - <key name="xhr-monitor-enabled" type="b"> - <default>false</default> - <summary>XHR Monitor Enabled</summary> - <description>Whether the XHR monitor is always enabled.</description> - </key> - <key name="debugger-enabled" type="b"> - <default>false</default> - <summary>Debugger Enabled</summary> - <description>Whether the debugger is always enabled.</description> - </key> - <key name="profiler-enabled" type="b"> - <default>false</default> - <summary>Profiler Enabled</summary> - <description>Whether the profiler is always enabled.</description> - </key> - <key name="frontend-settings" type="s"> - <default>''</default> - <summary>Misc Inspector Frontend Settings</summary> - <description>Miscelaneous Settings managed by the Inspector Frontend</description> - </key> - </schema> -</schemalist> diff --git a/Source/WebKit/gtk/tests/testcopyandpaste.c b/Source/WebKit/gtk/tests/testcopyandpaste.c index 6d1b48080..7d8dd8f0d 100644 --- a/Source/WebKit/gtk/tests/testcopyandpaste.c +++ b/Source/WebKit/gtk/tests/testcopyandpaste.c @@ -111,7 +111,6 @@ static void load_status_cb(WebKitWebView* webView, GParamSpec* spec, gpointer da gboolean map_event_cb(GtkWidget *widget, GdkEvent* event, gpointer data) { - gtk_widget_grab_focus(widget); CopyAndPasteFixture* fixture = (CopyAndPasteFixture*)data; webkit_web_view_load_string(fixture->webView, fixture->info->page, "text/html", "utf-8", "file://"); @@ -137,6 +136,8 @@ static void test_copy_and_paste(CopyAndPasteFixture* fixture, gconstpointer data static CopyAndPasteFixture* currentFixture; static JSValueRef runPasteTestCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { + gtk_widget_grab_focus(GTK_WIDGET(currentFixture->webView)); + // Simulate a paste keyboard sequence. GdkEvent* event = gdk_event_new(GDK_KEY_PRESS); event->key.keyval = gdk_unicode_to_keyval('v'); diff --git a/Source/WebKit/gtk/tests/testkeyevents.c b/Source/WebKit/gtk/tests/testkeyevents.c index cf33d4abe..b55b4bcaf 100644 --- a/Source/WebKit/gtk/tests/testkeyevents.c +++ b/Source/WebKit/gtk/tests/testkeyevents.c @@ -118,7 +118,6 @@ static void test_keypress_events_load_status_cb(WebKitWebView* webView, GParamSp gboolean map_event_cb(GtkWidget *widget, GdkEvent* event, gpointer data) { - gtk_widget_grab_focus(widget); KeyEventFixture* fixture = (KeyEventFixture*)data; webkit_web_view_load_string(fixture->webView, fixture->info->page, "text/html", "utf-8", "file://"); @@ -131,6 +130,7 @@ static void setup_keyevent_test(KeyEventFixture* fixture, gconstpointer data, GC g_signal_connect(fixture->window, "map-event", G_CALLBACK(map_event_cb), fixture); + gtk_widget_grab_focus(GTK_WIDGET(fixture->webView)); gtk_widget_show(fixture->window); gtk_widget_show(GTK_WIDGET(fixture->webView)); gtk_window_present(GTK_WINDOW(fixture->window)); diff --git a/Source/WebKit/gtk/tests/testwebplugindatabase.c b/Source/WebKit/gtk/tests/testwebplugindatabase.c index db2529f3a..f5e23d08a 100644 --- a/Source/WebKit/gtk/tests/testwebplugindatabase.c +++ b/Source/WebKit/gtk/tests/testwebplugindatabase.c @@ -44,7 +44,7 @@ static void test_webkit_web_plugin_database_get_plugins() for (p = pluginList; p; p = p->next) { WebKitWebPlugin* plugin = (WebKitWebPlugin*)p->data; if (!g_strcmp0(webkit_web_plugin_get_name(plugin), "WebKit Test PlugIn") && - !g_strcmp0(webkit_web_plugin_get_description(plugin), "Simple Netscape plug-in that handles test content for WebKit")) { + !g_strcmp0(webkit_web_plugin_get_description(plugin), "Simple Netscape® plug-in that handles test content for WebKit")) { found = TRUE; enabled = webkit_web_plugin_get_enabled(plugin); webkit_web_plugin_set_enabled(plugin, FALSE); @@ -60,7 +60,7 @@ static void test_webkit_web_plugin_database_get_plugins() for (p = pluginList; p; p = p->next) { WebKitWebPlugin* plugin = (WebKitWebPlugin*)p->data; if (!g_strcmp0(webkit_web_plugin_get_name(plugin), "WebKit Test PlugIn") && - !g_strcmp0(webkit_web_plugin_get_description(plugin), "Simple Netscape plug-in that handles test content for WebKit")) + !g_strcmp0(webkit_web_plugin_get_description(plugin), "Simple Netscape® plug-in that handles test content for WebKit")) enabled = webkit_web_plugin_get_enabled(plugin); } webkit_web_plugin_database_plugins_list_free(pluginList); diff --git a/Source/WebKit/gtk/tests/testwebview.c b/Source/WebKit/gtk/tests/testwebview.c index 41cf308f6..ab3bd5576 100644 --- a/Source/WebKit/gtk/tests/testwebview.c +++ b/Source/WebKit/gtk/tests/testwebview.c @@ -382,6 +382,121 @@ static void test_webkit_web_view_in_offscreen_window_does_not_crash() g_main_loop_unref(loop); } +static void test_webkit_web_view_does_not_steal_focus() +{ + loop = g_main_loop_new(NULL, TRUE); + + GtkWidget *window = gtk_offscreen_window_new(); + GtkWidget *webView = webkit_web_view_new(); + GtkWidget *entry = gtk_entry_new(); + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + + gtk_container_add(GTK_CONTAINER(box), webView); + gtk_container_add(GTK_CONTAINER(box), entry); + gtk_container_add(GTK_CONTAINER(window), box); + gtk_widget_show_all(window); + + gtk_widget_grab_focus(entry); + g_assert(gtk_widget_is_focus(entry)); + + g_signal_connect(webView, "notify::load-status", G_CALLBACK(idle_quit_loop_cb), NULL); + webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(webView), + "<html><body>" + " <input id=\"entry\" type=\"text\"/>" + " <script>" + " document.getElementById(\"entry\").focus();" + " </script>" + "</body></html>", "file://"); + + g_main_loop_run(loop); + + g_assert(gtk_widget_is_focus(entry)); + + gtk_widget_destroy(window); + g_main_loop_unref(loop); +} + +static gboolean emitKeyStroke(WebKitWebView* webView) +{ + GdkEvent* pressEvent = gdk_event_new(GDK_KEY_PRESS); + pressEvent->key.keyval = GDK_KEY_f; + GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(webView)); + pressEvent->key.window = window; + g_object_ref(pressEvent->key.window); + + GdkDeviceManager* manager = gdk_display_get_device_manager(gdk_window_get_display(window)); + gdk_event_set_device(pressEvent, gdk_device_manager_get_client_pointer(manager)); + + // When synthesizing an event, an invalid hardware_keycode value + // can cause it to be badly processed by Gtk+. + GdkKeymapKey* keys; + gint n_keys; + if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), GDK_KEY_f, &keys, &n_keys)) { + pressEvent->key.hardware_keycode = keys[0].keycode; + g_free(keys); + } + + GdkEvent* releaseEvent = gdk_event_copy(pressEvent); + gtk_main_do_event(pressEvent); + gdk_event_free(pressEvent); + releaseEvent->key.type = GDK_KEY_RELEASE; + gtk_main_do_event(releaseEvent); + gdk_event_free(releaseEvent); + + return FALSE; +} + +static gboolean entering_fullscreen_cb(WebKitWebView* webView, GObject* element, gboolean blocked) +{ + if (blocked) + g_main_loop_quit(loop); + else + g_timeout_add(200, (GSourceFunc) emitKeyStroke, webView); + return blocked; +} + +static gboolean leaving_fullscreen_cb(WebKitWebView* webView, GObject* element, gpointer data) +{ + g_main_loop_quit(loop); + return FALSE; +} + +static void test_webkit_web_view_fullscreen(gconstpointer blocked) +{ + GtkWidget* window; + GtkWidget* web_view; + WebKitWebSettings *settings; + + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + web_view = webkit_web_view_new(); + + settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(web_view)); + g_object_set(settings, "enable-fullscreen", TRUE, NULL); + webkit_web_view_set_settings(WEBKIT_WEB_VIEW(web_view), settings); + + gtk_container_add(GTK_CONTAINER(window), web_view); + + gtk_widget_show_all(window); + + loop = g_main_loop_new(NULL, TRUE); + + g_signal_connect(web_view, "entering-fullscreen", G_CALLBACK(entering_fullscreen_cb), (gpointer) blocked); + g_signal_connect(web_view, "leaving-fullscreen", G_CALLBACK(leaving_fullscreen_cb), NULL); + + webkit_web_view_load_string(WEBKIT_WEB_VIEW(web_view), "<html><body>" + "<script>" + "var eventName = 'keypress';" + "document.addEventListener(eventName, function () {" + " document.documentElement.webkitRequestFullScreen();" + "}, false);" + "</script></body></html>", NULL, NULL, NULL); + + g_timeout_add(100, (GSourceFunc) emitKeyStroke, WEBKIT_WEB_VIEW(web_view)); + g_main_loop_run(loop); + + gtk_widget_destroy(window); +} + int main(int argc, char** argv) { SoupServer* server; @@ -410,6 +525,9 @@ int main(int argc, char** argv) g_test_add_func("/webkit/webview/grab_focus", test_webkit_web_view_grab_focus); g_test_add_func("/webkit/webview/window-features", test_webkit_web_view_window_features); g_test_add_func("/webkit/webview/webview-in-offscreen-window-does-not-crash", test_webkit_web_view_in_offscreen_window_does_not_crash); + g_test_add_func("/webkit/webview/webview-does-not-steal-focus", test_webkit_web_view_does_not_steal_focus); + g_test_add_data_func("/webkit/webview/fullscreen", GINT_TO_POINTER(FALSE), test_webkit_web_view_fullscreen); + g_test_add_data_func("/webkit/webview/fullscreen-blocked", GINT_TO_POINTER(TRUE), test_webkit_web_view_fullscreen); return g_test_run (); } diff --git a/Source/WebKit/gtk/webkit/webkitglobals.cpp b/Source/WebKit/gtk/webkit/webkitglobals.cpp index 3967c6376..bc5d72604 100644 --- a/Source/WebKit/gtk/webkit/webkitglobals.cpp +++ b/Source/WebKit/gtk/webkit/webkitglobals.cpp @@ -336,12 +336,6 @@ void webkitInit() soup_session_add_feature(session, authDialog); g_object_unref(authDialog); - SoupSessionFeature* sniffer = static_cast<SoupSessionFeature*>(g_object_new(SOUP_TYPE_CONTENT_SNIFFER, NULL)); - soup_session_add_feature(session, sniffer); - g_object_unref(sniffer); - - soup_session_add_feature_by_type(session, SOUP_TYPE_CONTENT_DECODER); - #if USE(CLUTTER) gtk_clutter_init(0, 0); #endif diff --git a/Source/WebKit/gtk/webkit/webkitwebinspector.cpp b/Source/WebKit/gtk/webkit/webkitwebinspector.cpp index c93c2bdb2..692079f68 100644 --- a/Source/WebKit/gtk/webkit/webkitwebinspector.cpp +++ b/Source/WebKit/gtk/webkit/webkitwebinspector.cpp @@ -577,42 +577,3 @@ void webkit_web_inspector_execute_script(WebKitWebInspector* webInspector, long WebKitWebInspectorPrivate* priv = webInspector->priv; priv->page->inspectorController()->evaluateForTestInFrontend(callId, script); } - -#ifdef HAVE_GSETTINGS -static bool isSchemaAvailable(const char* schemaID) -{ - const char* const* availableSchemas = g_settings_list_schemas(); - char* const* iter = const_cast<char* const*>(availableSchemas); - - while (*iter) { - if (g_str_equal(schemaID, *iter)) - return true; - iter++; - } - - return false; -} - -GSettings* inspectorGSettings() -{ - static GSettings* settings = 0; - if (settings) - return settings; - - // Unfortunately GSettings will abort the process execution if the schema is not - // installed, which is the case for when running tests, or even the introspection dump - // at build time, so check if we have the schema before trying to initialize it. - const gchar* schemaID = "org.webkitgtk-"WEBKITGTK_API_VERSION_STRING".inspector"; - if (!isSchemaAvailable(schemaID)) { - - // This warning is very common on the build bots, which hides valid warnings. - // Skip printing it if we are running inside DumpRenderTree. - if (!DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled()) - g_warning("GSettings schema not found - settings will not be used or saved."); - return 0; - } - - settings = g_settings_new(schemaID); - return settings; -} -#endif diff --git a/Source/WebKit/gtk/webkit/webkitwebinspectorprivate.h b/Source/WebKit/gtk/webkit/webkitwebinspectorprivate.h index 46d57b0b8..64ba09a5d 100644 --- a/Source/WebKit/gtk/webkit/webkitwebinspectorprivate.h +++ b/Source/WebKit/gtk/webkit/webkitwebinspectorprivate.h @@ -25,10 +25,6 @@ extern "C" { -#ifdef HAVE_GSETTINGS -GSettings* inspectorGSettings(); -#endif - void webkit_web_inspector_set_inspector_client(WebKitWebInspector*, WebCore::Page*); void webkit_web_inspector_set_web_view(WebKitWebInspector*, WebKitWebView*); diff --git a/Source/WebKit/gtk/webkit/webkitwebsettings.cpp b/Source/WebKit/gtk/webkit/webkitwebsettings.cpp index d91c3bbf3..bf6ff600d 100644 --- a/Source/WebKit/gtk/webkit/webkitwebsettings.cpp +++ b/Source/WebKit/gtk/webkit/webkitwebsettings.cpp @@ -183,7 +183,7 @@ static String chromeUserAgent() DEFINE_STATIC_LOCAL(const String, uaVersion, (makeString(String::number(WEBKIT_USER_AGENT_MAJOR_VERSION), '.', String::number(WEBKIT_USER_AGENT_MINOR_VERSION), '+'))); DEFINE_STATIC_LOCAL(const String, staticUA, (makeString("Mozilla/5.0 (", webkitPlatform(), webkitOSVersion(), ") AppleWebKit/", uaVersion) + - makeString(" (KHTML, like Gecko) Chromium/15.0.874.120 Chrome/15.0.874.120 Safari/", uaVersion))); + makeString(" (KHTML, like Gecko) Chromium/17.0.963.56 Chrome/17.0.963.56 Safari/", uaVersion))); return staticUA; } diff --git a/Source/WebKit/gtk/webkit/webkitwebview.cpp b/Source/WebKit/gtk/webkit/webkitwebview.cpp index c22461c74..89b9c228f 100644 --- a/Source/WebKit/gtk/webkit/webkitwebview.cpp +++ b/Source/WebKit/gtk/webkit/webkitwebview.cpp @@ -212,6 +212,8 @@ enum { RESOURCE_LOAD_FINISHED, RESOURCE_CONTENT_LENGTH_RECEIVED, RESOURCE_LOAD_FAILED, + ENTERING_FULLSCREEN, + LEAVING_FULLSCREEN, LAST_SIGNAL }; @@ -639,6 +641,9 @@ static gboolean webkit_web_view_expose_event(GtkWidget* widget, GdkEventExpose* copyRectFromCairoSurfaceToContext(WEBKIT_WEB_VIEW(widget)->priv->backingStore->cairoSurface(), cr.get(), IntSize(), IntRect(rects.get()[i])); } + + // Chaining up to the parent forces child widgets to be drawn. + GTK_WIDGET_CLASS(webkit_web_view_parent_class)->expose_event(widget, event); return FALSE; } #else @@ -667,6 +672,8 @@ static gboolean webkit_web_view_draw(GtkWidget* widget, cairo_t* cr) } cairo_rectangle_list_destroy(rectList); + // Chaining up to the parent forces child widgets to be drawn. + GTK_WIDGET_CLASS(webkit_web_view_parent_class)->draw(widget, cr); return FALSE; } #endif // GTK_API_VERSION_2 @@ -1295,6 +1302,16 @@ static gboolean webkit_web_view_real_should_allow_editing_action(WebKitWebView*) return TRUE; } +static gboolean webkit_web_view_real_entering_fullscreen(WebKitWebView* webView) +{ + return FALSE; +} + +static gboolean webkit_web_view_real_leaving_fullscreen(WebKitWebView* webView) +{ + return FALSE; +} + static void webkit_web_view_dispose(GObject* object) { WebKitWebView* webView = WEBKIT_WEB_VIEW(object); @@ -2650,6 +2667,59 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) G_TYPE_NONE, 1, WEBKIT_TYPE_VIEWPORT_ATTRIBUTES); + /** + * WebKitWebView::entering-fullscreen: + * @web_view: the #WebKitWebView on which the signal is emitted. + * @element: the #WebKitDOMHTMLElement which has requested full screen display. + * + * Emitted when JavaScript code calls + * <function>element.webkitRequestFullScreen</function>. If the + * signal is not handled the WebView will proceed to full screen + * its top level window. This signal can be used by client code to + * request permission to the user prior doing the full screen + * transition and eventually prepare the top-level window + * (e.g. hide some widgets that would otherwise be part of the + * full screen window). + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to continue emission of the event. + * + * Since: 1.9.0 + */ + webkit_web_view_signals[ENTERING_FULLSCREEN] = + g_signal_new("entering-fullscreen", + G_TYPE_FROM_CLASS(webViewClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebViewClass, entering_fullscreen), + g_signal_accumulator_true_handled, 0, + webkit_marshal_BOOLEAN__OBJECT, + G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_DOM_HTML_ELEMENT); + + + /** + * WebKitWebView::leaving-fullscreen: + * @web_view: the #WebKitWebView on which the signal is emitted. + * @element: the #WebKitDOMHTMLElement which is currently displayed full screen. + * + * Emitted when the WebView is about to restore its top level + * window out of its full screen state. This signal can be used by + * client code to restore widgets hidden during the + * entering-fullscreen stage for instance. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to continue emission of the event. + * + * Since: 1.9.0 + */ + webkit_web_view_signals[LEAVING_FULLSCREEN] = + g_signal_new("leaving-fullscreen", + G_TYPE_FROM_CLASS(webViewClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebViewClass, leaving_fullscreen), + g_signal_accumulator_true_handled, 0, + webkit_marshal_BOOLEAN__OBJECT, + G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_DOM_HTML_ELEMENT); + /* * WebKitWebView::resource-response-received * @webView: the object which received the signal @@ -2758,6 +2828,8 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) webViewClass->redo = webkit_web_view_real_redo; webViewClass->move_cursor = webkit_web_view_real_move_cursor; webViewClass->should_allow_editing_action = webkit_web_view_real_should_allow_editing_action; + webViewClass->entering_fullscreen = webkit_web_view_real_entering_fullscreen; + webViewClass->leaving_fullscreen = webkit_web_view_real_leaving_fullscreen; GObjectClass* objectClass = G_OBJECT_CLASS(webViewClass); objectClass->dispose = webkit_web_view_dispose; @@ -3417,11 +3489,6 @@ static void webkit_web_view_init(WebKitWebView* webView) pageClients.dragClient = new WebKit::DragClient(webView); pageClients.inspectorClient = new WebKit::InspectorClient(webView); -#if ENABLE(DEVICE_ORIENTATION) - pageClients.deviceMotionClient = static_cast<WebCore::DeviceMotionClient*>(new DeviceMotionClientGtk); - pageClients.deviceOrientationClient = static_cast<WebCore::DeviceOrientationClient*>(new DeviceOrientationClientGtk); -#endif - #if ENABLE(CLIENT_BASED_GEOLOCATION) if (DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled()) pageClients.geolocationClient = new GeolocationClientMock; @@ -3431,6 +3498,11 @@ static void webkit_web_view_init(WebKitWebView* webView) priv->corePage = new Page(pageClients); +#if ENABLE(DEVICE_ORIENTATION) + WebCore::provideDeviceMotionTo(priv->corePage, new DeviceMotionClientGtk); + WebCore::provideDeviceOrientationTo(priv->corePage, new DeviceOrientationClientGtk); +#endif + #if ENABLE(CLIENT_BASED_GEOLOCATION) if (DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled()) static_cast<GeolocationClientMock*>(pageClients.geolocationClient)->setController(priv->corePage->geolocationController()); diff --git a/Source/WebKit/gtk/webkit/webkitwebview.h b/Source/WebKit/gtk/webkit/webkitwebview.h index 678e32966..2a15b53c6 100644 --- a/Source/WebKit/gtk/webkit/webkitwebview.h +++ b/Source/WebKit/gtk/webkit/webkitwebview.h @@ -176,11 +176,11 @@ struct _WebKitWebViewClass { void (* undo) (WebKitWebView *web_view); void (* redo) (WebKitWebView *web_view); gboolean (* should_allow_editing_action) (WebKitWebView *web_view); + gboolean (* entering_fullscreen) (WebKitWebView *web_view); + gboolean (* leaving_fullscreen) (WebKitWebView *web_view); /* Padding for future expansion */ void (*_webkit_reserved0) (void); - void (*_webkit_reserved1) (void); - void (*_webkit_reserved2) (void); }; WEBKIT_API GType diff --git a/Source/WebKit/mac/ChangeLog b/Source/WebKit/mac/ChangeLog index bf1173720..898482ec1 100644 --- a/Source/WebKit/mac/ChangeLog +++ b/Source/WebKit/mac/ChangeLog @@ -1,3 +1,458 @@ +2012-02-24 Shinya Kawanaka <shinyak@chromium.org> + + SpellCheckRequest needs to know the context where the spellcheck happened. + https://bugs.webkit.org/show_bug.cgi?id=79320 + + Reviewed by Hajime Morita. + + * WebCoreSupport/WebEditorClient.h: + * WebCoreSupport/WebEditorClient.mm: + (WebEditorClient::requestCheckingOfString): + +2012-02-23 Andy Estes <aestes@apple.com> + + Rename [setS|s]uppressIncrementalRendering to [setS|s]uppressesIncrementalRendering and make it WebPreferences API. + https://bugs.webkit.org/show_bug.cgi?id=79433 + + Reviewed by Dan Bernstein. + + * WebCoreSupport/WebInspectorClient.mm: + (-[WebInspectorWindowController init]): + * WebView/WebPreferenceKeysPrivate.h: + * WebView/WebPreferences.h: + * WebView/WebPreferences.mm: + (+[WebPreferences initialize]): + (-[WebPreferences setSuppressesIncrementalRendering:]): + (-[WebPreferences suppressesIncrementalRendering]): + (-[WebPreferences setSuppressIncrementalRendering:]): + (-[WebPreferences suppressIncrementalRendering]): + * WebView/WebView.mm: + (-[WebView _preferencesChanged:]): + +2012-02-22 Hajime Morrita <morrita@chromium.org> + + NOTIFICATIONS should be implemented as PageSupplement + https://bugs.webkit.org/show_bug.cgi?id=79052 + + Reviewed by Adam Barth. + + * WebView/WebView.mm: + (-[WebView _commonInitializationWithFrameName:groupName:]): + +2012-02-21 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/WebEditorClient.h: + (WebEditorClient): + * WebCoreSupport/WebEditorClient.mm: + (WebEditorClient::shouldApplyStyle): + * WebView/WebFrame.mm: + (-[WebFrame _setTypingStyle:withUndoAction:]): + * WebView/WebHTMLView.mm: + (-[WebHTMLView _applyStyleToSelection:withUndoAction:]): + (-[WebHTMLView _changeCSSColorUsingSelector:inRange:]): + * WebView/WebView.mm: + (-[WebView applyStyle:]): + +2012-02-22 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/WebEditorClient.h: + (WebEditorClient): + * WebCoreSupport/WebEditorClient.mm: + (WebEditorClient::shouldApplyStyle): + * WebView/WebFrame.mm: + (-[WebFrame _setTypingStyle:withUndoAction:]): + * WebView/WebHTMLView.mm: + (-[WebHTMLView _applyStyleToSelection:withUndoAction:]): + (-[WebHTMLView _changeCSSColorUsingSelector:inRange:]): + * WebView/WebView.mm: + (-[WebView applyStyle:]): + +2012-02-22 Jon Lee <jonlee@apple.com> + + Part of r108409 was incorrect, and incorporated an older version of a sub-patch. + This is the actual sub-patch that should have been submitted. + + * WebCoreSupport/WebNotificationClient.h: + * WebCoreSupport/WebNotificationClient.mm: + (WebNotificationClient::show): + (WebNotificationClient::cancel): + (WebNotificationClient::clearNotifications): + (WebNotificationClient::notificationObjectDestroyed): + (WebNotificationClient::notificationControllerDestroyed): + +2012-02-21 Jon Lee <jonlee@apple.com> + + Build fix. Push ENABLE_NOTIFICATIONS into .mm file. + + * WebCoreSupport/WebNotificationClient.h: + * WebView/WebNotification.h: + * WebView/WebNotification.mm: + (-[WebNotification title]): + (-[WebNotification body]): + (-[WebNotification origin]): + (-[WebNotification notificationID]): + (-[WebNotification dispatchShowEvent]): + (-[WebNotification dispatchCloseEvent]): + (-[WebNotification dispatchClickEvent]): + (-[WebNotification dispatchErrorEvent]): + +2012-02-21 John Sullivan <sullivan@apple.com> + + Build fix. + + * WebView/WebUIDelegatePrivate.h: + Added @class declarations for DOMNode and DOMElement. + +2012-02-21 Jon Lee <jonlee@apple.com> + + Build fix for r108409. + + * WebCoreSupport/WebNotificationClient.h: + (WebCore): + * WebCoreSupport/WebNotificationClient.mm: + * WebView/WebNotification.h: + (WebSecurityOrigin): + * WebView/WebNotification.mm: + (core): + (-[WebNotification initWithCoreNotification:notificationID:]): + +2012-02-21 Jon Lee <jonlee@apple.com> + + Bring notifications support to WK1 mac: permission requests + https://bugs.webkit.org/show_bug.cgi?id=78783 + <rdar://problem/10610578> + + Reviewed by Anders Carlsson. + + * WebCoreSupport/WebNotificationClient.h: + * WebCoreSupport/WebNotificationClient.mm: Create policy listener, which conforms to the + WebAllowDenyPolicyListener protocol, similar to geolocation. + (WebNotificationClient::requestPermission): + (WebNotificationClient::checkPermission): + (-[WebNotificationPolicyListener initWithCallback:]): + (-[WebNotificationPolicyListener allow]): Call the callback. + (-[WebNotificationPolicyListener deny]): Call the callback. + * WebView/WebUIDelegatePrivate.h: Define new UI delegate method to ask the user to decide a + policy for navigations. + + ==== + Bring notifications support to WK1 mac: showing, canceling, removing notifications + + Create a WebKit wrapper object for WebCore::Notification, which also keeps track of an assigned + ID. + * WebView/WebNotification.h: Added. + (WebSecurityOrigin): + * WebView/WebNotification.mm: Added. + (core): + (-[WebNotification initWithCoreNotification:notificationID:]): + (-[WebNotification init]): + (-[WebNotification dealloc]): + (-[WebNotification title]): + (-[WebNotification body]): + (-[WebNotification origin]): + (-[WebNotification notificationID]): + (-[WebNotification dispatchShowEvent]): + (-[WebNotification dispatchCloseEvent]): + (-[WebNotification dispatchClickEvent]): + (-[WebNotification dispatchErrorEvent]): + * WebView/WebNotificationInternal.h: Added. + (WebCore): Internal category to allow creating instances with WebCore objects. + + Extend WebView to include a WebNotificationProvider, which clients implement. + * WebView/WebViewData.h: Add a private member for the provider. + * WebView/WebViewPrivate.h: + * Define an enum WebNotificationPermission that mirrors WebCore::NotificationPresenter::Permission + that client which implement the provider can use to return policy decisions. + * Define WebNotificationProvider. + * Category WebViewNotification extends WebView with methods that set and manager the + notification provider, and handle events from the platform notifications. + * WebView/WebView.mm: + (-[WebView _setNotificationProvider:]): Sets the provider when initializing the WebView. + (-[WebView _notificationControllerDestroyed]): + (-[WebView _notificationProvider]): + (-[WebView _notificationDidShow:]): + (-[WebView _notificationDidClick:]): + (-[WebView _notificationsDidClose:]): + + * WebCoreSupport/WebNotificationClient.h: Add variables that map between WebCore::Notification + instances, their assigned IDs, their contexts, and corresponding WebKit wrapper objects. + * WebCoreSupport/WebNotificationClient.mm: + (generateNotificationID): Created unique IDs for each shown notification. + (WebNotificationClient::show): Create wrapper object for notification, assign ID, cache the + mappings between the objects, and forward it to the provider. + (WebNotificationClient::cancel): + (WebNotificationClient::clearNotifications): Clear all notifications associated with the + provided context. + (WebNotificationClient::notificationObjectDestroyed): Remove the notification from the maps. + (WebNotificationClient::notificationControllerDestroyed): If the controller is destroyed, tell + the provider to clear of the notifications related to this web view. + + ==== + (Prep work for) Bring notifications support to WK1 mac + + Rename WebGeolocationPolicyListener. The interface is generic enough to be reused for + notification requests. To avoid having to create a new listener type, instead rename it + to WebAllowDenyPolicyListener. + * WebView/WebUIDelegatePrivate.h: Rename the protocol. + * WebCoreSupport/WebGeolocationClient.mm: Refactor geolocation request listener to use + new name. + + Add preference to keep track of whether notifications are enabled in general. + * WebView/WebPreferenceKeysPrivate.h: Add WebNotificationsEnabledKey for storing the + preference. + * WebView/WebPreferences.mm: + (+[WebPreferences initialize]): By default have them enabled. + (-[WebPreferences setNotificationsEnabled:]): + (-[WebPreferences notificationsEnabled]): + * WebView/WebPreferencesPrivate.h: + + Add a stringValue method that exposes WebCore::SecurityOrigin::toString() for storing the + notification policy for a given origin. + * WebCoreSupport/WebSecurityOrigin.mm: + (-[WebSecurityOrigin stringValue]): + * WebCoreSupport/WebSecurityOriginPrivate.h: + +2012-02-21 Sam Weinig <sam@webkit.org> + + Attempt to fix the Snow Leopard build. + + * Configurations/Base.xcconfig: + +2012-02-21 Sam Weinig <sam@webkit.org> + + Use libc++ when building with Clang on Mac + https://bugs.webkit.org/show_bug.cgi?id=78981 + + Reviewed by Dan Bernstein. + + * Configurations/Base.xcconfig: + +2012-02-17 Mihnea Ovidenie <mihnea@adobe.com> + + CSS regions enabled by default + https://bugs.webkit.org/show_bug.cgi?id=78525 + + Reviewed by David Hyatt. + + Add a runtime preference to enable/disable regions functionality at runtime(WebKitCSSRegionsEnabled). + CSSRegions are still enabled by default. + In DRT, use layoutTestController.overridePreference("WebKitCSSRegionsEnabled", "0") to disable the css regions functionality. + + * WebView/WebPreferenceKeysPrivate.h: + * WebView/WebPreferences.mm: + (+[WebPreferences initialize]): + (-[WebPreferences cssRegionsEnabled]): + (-[WebPreferences setCSSRegionsEnabled:]): + * WebView/WebPreferencesPrivate.h: + * WebView/WebView.mm: + (-[WebView _preferencesChanged:]): + +2012-02-17 Enrica Casucci <enrica@apple.com> + + Refactor DragData class to use PlatformStrategies in the Mac implementation. + https://bugs.webkit.org/show_bug.cgi?id=78768 + + Reviewed by Darin Adler. + + * WebCoreSupport/WebPlatformStrategies.h: Added color() method. + * WebCoreSupport/WebPlatformStrategies.mm: + (WebPlatformStrategies::color): + +2012-02-16 Brady Eidson <beidson@apple.com> + + <rdar://problem/10616280> and https://bugs.webkit.org/show_bug.cgi?id=78767 + REGRESSION (r90471) - iAd Producer 2.0.1 produces blank pages + + Reviewed by Sam Weinig. + + * WebView/WebView.mm: + (-[WebView _needsIsLoadingInAPISenseQuirk]): + (-[WebView _preferencesChanged:]): + +2012-02-15 Enrica Casucci <enrica@apple.com> + + Refactor ClipboardMac class to use PlatformStrategies. + https://bugs.webkit.org/show_bug.cgi?id=78554 + + Reviewed by Anders Carlsson. + + * WebCoreSupport/WebDragClient.h: Changed methods signature to use name based pasteboard. + * WebCoreSupport/WebDragClient.mm: Ditto. + (WebDragClient::willPerformDragSourceAction): + (WebDragClient::startDrag): + (WebDragClient::declareAndWriteDragImage): + * WebCoreSupport/WebPlatformStrategies.h: Added new methods. + * WebCoreSupport/WebPlatformStrategies.mm: + (WebPlatformStrategies::changeCount): + (WebPlatformStrategies::uniqueName): + +2012-02-15 Sadrul Habib Chowdhury <sadrul@chromium.org> + + Notify ChromeClient when touch-event handlers are installed/removed. + https://bugs.webkit.org/show_bug.cgi?id=77440 + + Reviewed by Darin Fisher and Ryosuke Niwa. + + * WebCoreSupport/WebChromeClient.h: + +2012-02-14 Matt Lilek <mrl@apple.com> + + Don't ENABLE_DASHBOARD_SUPPORT unconditionally on all Mac platforms + https://bugs.webkit.org/show_bug.cgi?id=78629 + + Reviewed by David Kilzer. + + * Configurations/FeatureDefines.xcconfig: + +2012-02-14 Alexey Proskuryakov <ap@apple.com> + + [Mac][Win][WK2] Switch to RFC 6455 protocol for WebSockets + https://bugs.webkit.org/show_bug.cgi?id=78541 + <rdar://problem/10036695> + + Reviewed by Kent Tamura. + + * WebView/WebPreferences.mm: (+[WebPreferences initialize]): Changed default value of the + preference. + +2012-02-11 Nikolas Zimmermann <nzimmermann@rim.com> + + Convert svg/animations to use SMIL methods for driving the timeline + https://bugs.webkit.org/show_bug.cgi?id=78422 + + Reviewed by Dirk Schulze. + + Remove SVG animation sampling functionality provided for DRT, which no longer uses it. + Instead we switched the svg/animations tests to use SVGSVGElement.setCurrentTime. + + * WebKit.order: + * WebView/WebFrame.mm: + * WebView/WebFramePrivate.h: + +2012-02-13 Enrica Casucci <enrica@apple.com> + + Refactor Mac platform implementation of the Pasteboard class to use Platform Strategies. + https://bugs.webkit.org/show_bug.cgi?id=78282 + + This patch removes any accesss to the NSPasteboard object from the Pasteboard class which + now makes use of a new pasteboardStrategy object that is implemented both in WebKit and + WebKit2. The actual access to NSPasteboard is now performed inside the PlatformPasteboard + class. Currently both WebKit and WebKit2 use the same implementation of the PasteboardStrategy + interface but this one more step in the direction of removing access to NSPasteboard from + the WebProcess. + As part of the refactoring the I've reduced to a minimum the use of OBJ-C classes. + + Reviewed by Anders Carlsson. + + * WebCoreSupport/WebPlatformStrategies.h: Added PasteboardStrategy. + * WebCoreSupport/WebPlatformStrategies.mm: Added implementation of PasteboardStrategy interface. + (WebPlatformStrategies::createPasteboardStrategy): + (WebPlatformStrategies::getTypes): + (WebPlatformStrategies::bufferForType): + (WebPlatformStrategies::getPathnamesForType): + (WebPlatformStrategies::stringForType): + (WebPlatformStrategies::copy): + (WebPlatformStrategies::setTypes): + (WebPlatformStrategies::setBufferForType): + (WebPlatformStrategies::setPathnamesForType): + (WebPlatformStrategies::setStringForType): + +2012-02-12 Hajime Morrita <morrita@chromium.org> + + Page should have less intrusive way to associate API implementation objects. + https://bugs.webkit.org/show_bug.cgi?id=78085 + + Reviewed by Adam Barth. + + * WebView/WebView.mm: + (-[WebView _commonInitializationWithFrameName:groupName:]): + +2012-02-11 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r107435. + http://trac.webkit.org/changeset/107435 + https://bugs.webkit.org/show_bug.cgi?id=78410 + + It broke the Qt build (Requested by Ossy on #webkit). + + * WebCoreSupport/WebPlatformStrategies.h: + (WebPlatformStrategies): + * WebCoreSupport/WebPlatformStrategies.mm: + (WebPlatformStrategies::addVisitedLink): + +2012-02-10 Adam Klein <adamk@chromium.org> + + Enable MUTATION_OBSERVERS by default on all platforms + https://bugs.webkit.org/show_bug.cgi?id=78196 + + Reviewed by Ojan Vafai. + + * Configurations/FeatureDefines.xcconfig: + +2012-02-10 Enrica Casucci <enrica@apple.com> + + Refactor Mac platform implementation of the Pasteboard class to use Platform Strategies. + https://bugs.webkit.org/show_bug.cgi?id=78282 + + This patch removes any accesss to the NSPasteboard object from the Pasteboard class which + now makes use of a new pasteboardStrategy object that is implemented both in WebKit and + WebKit2. The actual access to NSPasteboard is now performed inside the PlatformPasteboard + class. Currently both WebKit and WebKit2 use the same implementation of the PasteboardStrategy + interface but this one more step in the direction of removing access to NSPasteboard from + the WebProcess. + As part of the refactoring the I've reduced to a minimum the use of OBJ-C classes. + + Reviewed by Anders Carlsson. + + * WebCoreSupport/WebPlatformStrategies.h: Added PasteboardStrategy. + * WebCoreSupport/WebPlatformStrategies.mm: Added implementation of PasteboardStrategy interface. + (WebPlatformStrategies::createPasteboardStrategy): + (WebPlatformStrategies::getTypes): + (WebPlatformStrategies::bufferForType): + (WebPlatformStrategies::getPathnamesForType): + (WebPlatformStrategies::stringForType): + (WebPlatformStrategies::copy): + (WebPlatformStrategies::setTypes): + (WebPlatformStrategies::setBufferForType): + (WebPlatformStrategies::setPathnamesForType): + (WebPlatformStrategies::setStringForType): + +2012-02-10 Benjamin Poulain <bpoulain@apple.com> + + [Mac] DYLIB_INSTALL_NAME_BASE should not be prefixed by the SDKROOT + https://bugs.webkit.org/show_bug.cgi?id=78320 + + Reviewed by Joseph Pecoraro. + + <rdar://problem/10839750> + + * Configurations/WebKit.xcconfig: + +2012-02-09 Alexey Proskuryakov <ap@apple.com> + + REGRESSION (r104885): Articles not displayed in Vienna RSS reader + https://bugs.webkit.org/show_bug.cgi?id=78280 + <rdar://problem/10762545> + + Reviewed by Oliver Hunt. + + * Misc/WebNSURLExtras.h: + * Misc/WebNSURLExtras.mm: (-[NSURL _webkit_URLFromURLOrPath]): + Added a method to create a URL from a path, similarly to what KURL used to do. + + * WebView/WebFrame.mm: (-[WebFrame loadData:MIMEType:textEncodingName:baseURL:]): + Use it in an API where a known regression occurred. + 2012-02-07 Antti Koivisto <antti@apple.com> REGRESSION (r106681): Null check missing in [WebFrame(WebInternal) _typingStyle] diff --git a/Source/WebKit/mac/Configurations/Base.xcconfig b/Source/WebKit/mac/Configurations/Base.xcconfig index 648332252..b62984744 100644 --- a/Source/WebKit/mac/Configurations/Base.xcconfig +++ b/Source/WebKit/mac/Configurations/Base.xcconfig @@ -65,6 +65,11 @@ WARNING_CFLAGS_iphoneos = $(WARNING_CFLAGS_BASE); WARNING_CFLAGS_iphonesimulator = $(WARNING_CFLAGS_BASE); WARNING_CFLAGS_macosx = $(WARNING_CFLAGS_BASE); +CLANG_CXX_LIBRARY = $(CLANG_CXX_LIBRARY_$(TARGET_MAC_OS_X_VERSION_MAJOR)); +CLANG_CXX_LIBRARY_1060 = libstdc++; +CLANG_CXX_LIBRARY_1070 = libc++; +CLANG_CXX_LIBRARY_1080 = libc++; +CLANG_CXX_LIBRARY_1090 = libc++; REAL_PLATFORM_NAME = $(REAL_PLATFORM_NAME_$(PLATFORM_NAME)); REAL_PLATFORM_NAME_ = $(REAL_PLATFORM_NAME_macosx); diff --git a/Source/WebKit/mac/Configurations/FeatureDefines.xcconfig b/Source/WebKit/mac/Configurations/FeatureDefines.xcconfig index f5bc9cf39..3e2090355 100644 --- a/Source/WebKit/mac/Configurations/FeatureDefines.xcconfig +++ b/Source/WebKit/mac/Configurations/FeatureDefines.xcconfig @@ -37,7 +37,8 @@ ENABLE_BLOB_macosx = ENABLE_BLOB; ENABLE_CLIENT_BASED_GEOLOCATION = $(ENABLE_CLIENT_BASED_GEOLOCATION_$(REAL_PLATFORM_NAME)); ENABLE_CLIENT_BASED_GEOLOCATION_macosx = ENABLE_CLIENT_BASED_GEOLOCATION; -ENABLE_DASHBOARD_SUPPORT = ENABLE_DASHBOARD_SUPPORT; +ENABLE_DASHBOARD_SUPPORT = $(ENABLE_DASHBOARD_SUPPORT_$(REAL_PLATFORM_NAME)); +ENABLE_DASHBOARD_SUPPORT_macosx = ENABLE_DASHBOARD_SUPPORT; ENABLE_DATALIST = $(ENABLE_DATALIST_$(REAL_PLATFORM_NAME)); ENABLE_DATALIST_macosx = ENABLE_DATALIST; @@ -95,7 +96,7 @@ ENABLE_MEDIA_SOURCE = ; ENABLE_MEDIA_STATISTICS = ; ENABLE_METER_TAG = ENABLE_METER_TAG; ENABLE_MHTML = ; -ENABLE_MUTATION_OBSERVERS = ; +ENABLE_MUTATION_OBSERVERS = ENABLE_MUTATION_OBSERVERS; ENABLE_NOTIFICATIONS = $(ENABLE_NOTIFICATIONS_$(REAL_PLATFORM_NAME)); ENABLE_NOTIFICATIONS_macosx = $(ENABLE_NOTIFICATIONS_macosx_$(TARGET_MAC_OS_X_VERSION_MAJOR)); diff --git a/Source/WebKit/mac/Configurations/Version.xcconfig b/Source/WebKit/mac/Configurations/Version.xcconfig index 20bc364c1..5344a720d 100644 --- a/Source/WebKit/mac/Configurations/Version.xcconfig +++ b/Source/WebKit/mac/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 535; -MINOR_VERSION = 20; +MINOR_VERSION = 23; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/Source/WebKit/mac/Configurations/WebKit.xcconfig b/Source/WebKit/mac/Configurations/WebKit.xcconfig index 7e0ac2979..0a0cf9f41 100644 --- a/Source/WebKit/mac/Configurations/WebKit.xcconfig +++ b/Source/WebKit/mac/Configurations/WebKit.xcconfig @@ -83,8 +83,8 @@ WEBKIT_FRAMEWORKS_DIR_macosx_USE_STAGING_INSTALL_PATH_NO = $(NORMAL_WEBKIT_FRAME WEBKIT_FRAMEWORKS_DIR_macosx_USE_STAGING_INSTALL_PATH_YES = $(SYSTEM_LIBRARY_DIR)/StagedFrameworks/Safari; NORMAL_PRODUCTION_FRAMEWORKS_DIR = $(NORMAL_PRODUCTION_FRAMEWORKS_DIR_$(REAL_PLATFORM_NAME)); -NORMAL_PRODUCTION_FRAMEWORKS_DIR_iphoneos = $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks; -NORMAL_PRODUCTION_FRAMEWORKS_DIR_iphonesimulator = $(PRODUCTION_FRAMEWORKS_DIR_iphoneos); +NORMAL_PRODUCTION_FRAMEWORKS_DIR_iphoneos = $(SYSTEM_LIBRARY_DIR)/PrivateFrameworks; +NORMAL_PRODUCTION_FRAMEWORKS_DIR_iphonesimulator = $(NORMAL_PRODUCTION_FRAMEWORKS_DIR_iphoneos); NORMAL_PRODUCTION_FRAMEWORKS_DIR_macosx = $(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks; PRODUCTION_FRAMEWORKS_DIR = $(PRODUCTION_FRAMEWORKS_DIR_$(REAL_PLATFORM_NAME)); diff --git a/Source/WebKit/mac/Misc/WebNSURLExtras.h b/Source/WebKit/mac/Misc/WebNSURLExtras.h index c7b266e93..6b170a7bb 100644 --- a/Source/WebKit/mac/Misc/WebNSURLExtras.h +++ b/Source/WebKit/mac/Misc/WebNSURLExtras.h @@ -69,6 +69,8 @@ - (NSString *)_webkit_suggestedFilenameWithMIMEType:(NSString *)MIMEType; +- (NSURL *)_webkit_URLFromURLOrPath; + @end @interface NSString (WebNSURLExtras) diff --git a/Source/WebKit/mac/Misc/WebNSURLExtras.mm b/Source/WebKit/mac/Misc/WebNSURLExtras.mm index b408bd4a3..c2351dd3d 100644 --- a/Source/WebKit/mac/Misc/WebNSURLExtras.mm +++ b/Source/WebKit/mac/Misc/WebNSURLExtras.mm @@ -883,6 +883,14 @@ static CFStringRef createStringWithEscapedUnsafeCharacters(CFStringRef string) return suggestedFilenameWithMIMEType(self, MIMEType); } +- (NSURL *)_webkit_URLFromURLOrPath +{ + if ([self scheme]) + return self; + + return [NSURL fileURLWithPath:[self absoluteString]]; +} + @end @implementation NSString (WebNSURLExtras) diff --git a/Source/WebKit/mac/WebCoreSupport/WebChromeClient.h b/Source/WebKit/mac/WebCoreSupport/WebChromeClient.h index 48ff09bba..66fa060b5 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebChromeClient.h +++ b/Source/WebKit/mac/WebCoreSupport/WebChromeClient.h @@ -189,6 +189,7 @@ public: #endif virtual void numWheelEventHandlersChanged(unsigned) OVERRIDE { } + virtual void numTouchEventHandlersChanged(unsigned) OVERRIDE { } virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const OVERRIDE { return false; } private: WebView *m_webView; diff --git a/Source/WebKit/mac/WebCoreSupport/WebDragClient.h b/Source/WebKit/mac/WebCoreSupport/WebDragClient.h index e472fb7ce..9d96b82c5 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebDragClient.h +++ b/Source/WebKit/mac/WebCoreSupport/WebDragClient.h @@ -36,7 +36,7 @@ public: virtual void dragControllerDestroyed() OVERRIDE; virtual WebCore::DragSourceAction dragSourceActionMaskForPoint(const WebCore::IntPoint& windowPoint) OVERRIDE; virtual void startDrag(WebCore::DragImageRef, const WebCore::IntPoint& dragPos, const WebCore::IntPoint& eventPos, WebCore::Clipboard*, WebCore::Frame*, bool linkDrag) OVERRIDE; - virtual void declareAndWriteDragImage(NSPasteboard*, DOMElement*, NSURL*, NSString*, WebCore::Frame*) OVERRIDE; + virtual void declareAndWriteDragImage(const String& pasteboardName, DOMElement*, NSURL*, NSString*, WebCore::Frame*) OVERRIDE; private: WebView* m_webView; }; diff --git a/Source/WebKit/mac/WebCoreSupport/WebDragClient.mm b/Source/WebKit/mac/WebCoreSupport/WebDragClient.mm index 9ba4b05dc..aff7ec2cf 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebDragClient.mm +++ b/Source/WebKit/mac/WebCoreSupport/WebDragClient.mm @@ -83,7 +83,7 @@ WebCore::DragSourceAction WebDragClient::dragSourceActionMaskForPoint(const IntP void WebDragClient::willPerformDragSourceAction(WebCore::DragSourceAction action, const WebCore::IntPoint& mouseDownPoint, WebCore::Clipboard* clipboard) { ASSERT(clipboard); - [[m_webView _UIDelegateForwarder] webView:m_webView willPerformDragSourceAction:(WebDragSourceAction)action fromPoint:mouseDownPoint withPasteboard:static_cast<WebCore::ClipboardMac*>(clipboard)->pasteboard()]; + [[m_webView _UIDelegateForwarder] webView:m_webView willPerformDragSourceAction:(WebDragSourceAction)action fromPoint:mouseDownPoint withPasteboard:[NSPasteboard pasteboardWithName:static_cast<WebCore::ClipboardMac*>(clipboard)->pasteboardName()]]; } void WebDragClient::startDrag(DragImageRef dragImage, const IntPoint& at, const IntPoint& eventPos, Clipboard* clipboard, Frame* frame, bool linkDrag) @@ -100,7 +100,7 @@ void WebDragClient::startDrag(DragImageRef dragImage, const IntPoint& at, const RetainPtr<WebHTMLView> topViewProtector = topHTMLView; [topHTMLView _stopAutoscrollTimer]; - NSPasteboard *pasteboard = static_cast<ClipboardMac*>(clipboard)->pasteboard(); + NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:static_cast<ClipboardMac*>(clipboard)->pasteboardName()]; NSImage *dragNSImage = dragImage.get(); WebHTMLView *sourceHTMLView = htmlView.get(); @@ -120,14 +120,14 @@ void WebDragClient::startDrag(DragImageRef dragImage, const IntPoint& at, const [topHTMLView dragImage:dragNSImage at:at offset:NSZeroSize event:event pasteboard:pasteboard source:sourceHTMLView slideBack:YES]; } -void WebDragClient::declareAndWriteDragImage(NSPasteboard* pasteboard, DOMElement* element, NSURL* URL, NSString* title, WebCore::Frame* frame) +void WebDragClient::declareAndWriteDragImage(const String& pasteboardName, DOMElement* element, NSURL* URL, NSString* title, WebCore::Frame* frame) { - ASSERT(pasteboard); + ASSERT(pasteboardName); ASSERT(element); WebHTMLView *source = getTopHTMLView(frame); WebArchive *archive = [element webArchive]; - [pasteboard _web_declareAndWriteDragImageForElement:element URL:URL title:title archive:archive source:source]; + [[NSPasteboard pasteboardWithName:pasteboardName] _web_declareAndWriteDragImageForElement:element URL:URL title:title archive:archive source:source]; } void WebDragClient::dragControllerDestroyed() diff --git a/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h b/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h index c70d6089d..c75fee09f 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h +++ b/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h @@ -61,7 +61,7 @@ public: virtual bool shouldInsertText(const WTF::String&, WebCore::Range*, WebCore::EditorInsertAction) OVERRIDE; virtual bool shouldChangeSelectedRange(WebCore::Range* fromRange, WebCore::Range* toRange, WebCore::EAffinity, bool stillSelecting) OVERRIDE; - virtual bool shouldApplyStyle(WebCore::CSSStyleDeclaration*, WebCore::Range*) OVERRIDE; + virtual bool shouldApplyStyle(WebCore::StylePropertySet*, WebCore::Range*) OVERRIDE; virtual bool shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range* rangeToBeReplaced) OVERRIDE; @@ -135,7 +135,7 @@ public: virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses) OVERRIDE; virtual void willSetInputMethodState() OVERRIDE; virtual void setInputMethodState(bool enabled) OVERRIDE; - virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&) OVERRIDE; + virtual void requestCheckingOfString(WebCore::SpellChecker*, const WebCore::TextCheckingRequest&) OVERRIDE; #if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) OVERRIDE; virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel) OVERRIDE; diff --git a/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm b/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm index fabdf6c6f..478553034 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm +++ b/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm @@ -241,10 +241,10 @@ bool WebEditorClient::isSelectTrailingWhitespaceEnabled() return [m_webView isSelectTrailingWhitespaceEnabled]; } -bool WebEditorClient::shouldApplyStyle(CSSStyleDeclaration* style, Range* range) +bool WebEditorClient::shouldApplyStyle(StylePropertySet* style, Range* range) { return [[m_webView _editingDelegateForwarder] webView:m_webView - shouldApplyStyle:kit(style) toElementsInDOMRange:kit(range)]; + shouldApplyStyle:kit(style->ensureCSSStyleDeclaration()) toElementsInDOMRange:kit(range)]; } bool WebEditorClient::shouldMoveRangeAfterDelete(Range* range, Range* rangeToBeReplaced) @@ -972,15 +972,15 @@ void WebEditorClient::setInputMethodState(bool) @end #endif -void WebEditorClient::requestCheckingOfString(WebCore::SpellChecker* sender, int sequence, WebCore::TextCheckingTypeMask checkingTypes, const String& text) +void WebEditorClient::requestCheckingOfString(WebCore::SpellChecker* sender, const WebCore::TextCheckingRequest& request) { #ifndef BUILDING_ON_LEOPARD - NSRange range = NSMakeRange(0, text.length()); + NSRange range = NSMakeRange(0, request.text().length()); NSRunLoop* currentLoop = [NSRunLoop currentRunLoop]; - [[NSSpellChecker sharedSpellChecker] requestCheckingOfString:text range:range types:NSTextCheckingAllSystemTypes options:0 inSpellDocumentWithTag:0 + [[NSSpellChecker sharedSpellChecker] requestCheckingOfString:request.text() range:range types:NSTextCheckingAllSystemTypes options:0 inSpellDocumentWithTag:0 completionHandler:^(NSInteger, NSArray* results, NSOrthography*, NSInteger) { [currentLoop performSelector:@selector(perform) - target:[[[WebEditorSpellCheckResponder alloc] initWithSender:sender sequence:sequence types:checkingTypes results:results] autorelease] + target:[[[WebEditorSpellCheckResponder alloc] initWithSender:sender sequence:request.sequence() types:request.mask() results:results] autorelease] argument:nil order:0 modes:[NSArray arrayWithObject:NSDefaultRunLoopMode]]; }]; #endif diff --git a/Source/WebKit/mac/WebCoreSupport/WebGeolocationClient.mm b/Source/WebKit/mac/WebCoreSupport/WebGeolocationClient.mm index b52b7bc64..541f40ccd 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebGeolocationClient.mm +++ b/Source/WebKit/mac/WebCoreSupport/WebGeolocationClient.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,7 +37,7 @@ using namespace WebCore; -@interface WebGeolocationPolicyListener : NSObject <WebGeolocationPolicyListener> +@interface WebGeolocationPolicyListener : NSObject <WebAllowDenyPolicyListener> { RefPtr<Geolocation> _geolocation; } diff --git a/Source/WebKit/mac/WebCoreSupport/WebInspectorClient.mm b/Source/WebKit/mac/WebCoreSupport/WebInspectorClient.mm index 14ebd1d65..2ae865951 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebInspectorClient.mm +++ b/Source/WebKit/mac/WebCoreSupport/WebInspectorClient.mm @@ -240,7 +240,7 @@ void WebInspectorFrontendClient::updateWindowTitle() const [preferences setMinimumFontSize:0]; [preferences setMinimumLogicalFontSize:9]; [preferences setPlugInsEnabled:NO]; - [preferences setSuppressIncrementalRendering:YES]; + [preferences setSuppressesIncrementalRendering:YES]; [preferences setTabsToLinks:NO]; [preferences setUserStyleSheetEnabled:NO]; diff --git a/Source/WebKit/mac/WebCoreSupport/WebNotificationClient.h b/Source/WebKit/mac/WebCoreSupport/WebNotificationClient.h index 82903ca59..a40ce81e5 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebNotificationClient.h +++ b/Source/WebKit/mac/WebCoreSupport/WebNotificationClient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,11 +25,20 @@ #import <WebCore/NotificationPresenter.h> +#if ENABLE(NOTIFICATIONS) +#import <WebCore/Notification.h> +#import <wtf/HashMap.h> +#import <wtf/RefPtr.h> +#import <wtf/RetainPtr.h> +#endif + namespace WebCore { +class Notification; class ScriptExecutionContext; class VoidCallback; } +@class WebNotification; @class WebView; class WebNotificationClient : public WebCore::NotificationPresenter { @@ -40,11 +49,18 @@ public: private: virtual bool show(WebCore::Notification*) OVERRIDE; virtual void cancel(WebCore::Notification*) OVERRIDE; + virtual void clearNotifications(WebCore::ScriptExecutionContext*) OVERRIDE; virtual void notificationObjectDestroyed(WebCore::Notification*) OVERRIDE; virtual void notificationControllerDestroyed() OVERRIDE; virtual void requestPermission(WebCore::ScriptExecutionContext*, PassRefPtr<WebCore::VoidCallback>) OVERRIDE; - virtual void cancelRequestsForPermission(WebCore::ScriptExecutionContext*) OVERRIDE; + virtual void cancelRequestsForPermission(WebCore::ScriptExecutionContext*) OVERRIDE { } virtual WebCore::NotificationPresenter::Permission checkPermission(WebCore::ScriptExecutionContext*) OVERRIDE; WebView *m_webView; +#if ENABLE(NOTIFICATIONS) + HashMap<RefPtr<WebCore::Notification>, RetainPtr<WebNotification> > m_notificationMap; + + typedef HashMap<RefPtr<WebCore::ScriptExecutionContext>, Vector<RetainPtr<WebNotification> > > NotificationContextMap; + NotificationContextMap m_notificationContextMap; +#endif }; diff --git a/Source/WebKit/mac/WebCoreSupport/WebNotificationClient.mm b/Source/WebKit/mac/WebCoreSupport/WebNotificationClient.mm index 80138e313..2f7cd5411 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebNotificationClient.mm +++ b/Source/WebKit/mac/WebCoreSupport/WebNotificationClient.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,49 +25,199 @@ #import "WebNotificationClient.h" -#import <WebCore/NotImplemented.h> -#import <WebCore/Notification.h> +#if ENABLE(NOTIFICATIONS) +#import "WebDelegateImplementationCaching.h" +#import "WebNotificationInternal.h" +#import "WebPreferencesPrivate.h" +#import "WebSecurityOriginInternal.h" +#import "WebUIDelegatePrivate.h" +#import "WebViewInternal.h" +#import <WebCore/BlockExceptions.h> +#import <WebCore/Page.h> +#import <WebCore/ScriptExecutionContext.h> +#endif using namespace WebCore; +#if ENABLE(NOTIFICATIONS) +@interface WebNotificationPolicyListener : NSObject <WebAllowDenyPolicyListener> +{ + RefPtr<VoidCallback> _callback; +} +- (id)initWithCallback:(PassRefPtr<VoidCallback>)callback; +@end +#endif + +#if ENABLE(NOTIFICATIONS) +static uint64_t generateNotificationID() +{ + static uint64_t uniqueNotificationID = 1; + return uniqueNotificationID++; +} +#endif + WebNotificationClient::WebNotificationClient(WebView *webView) : m_webView(webView) { } -bool WebNotificationClient::show(Notification*) +bool WebNotificationClient::show(Notification* notification) { - notImplemented(); +#if ENABLE(NOTIFICATIONS) + if (![m_webView _notificationProvider]) + return false; + + uint64_t notificationID = generateNotificationID(); + RetainPtr<WebNotification> webNotification = adoptNS([[WebNotification alloc] initWithCoreNotification:notification notificationID:notificationID]); + m_notificationMap.set(notification, webNotification); + + NotificationContextMap::iterator it = m_notificationContextMap.add(notification->scriptExecutionContext(), Vector<RetainPtr<WebNotification> >()).first; + it->second.append(webNotification); + + [[m_webView _notificationProvider] showNotification:webNotification.get() fromWebView:m_webView]; + return true; +#else + UNUSED_PARAM(notification); return false; +#endif +} + +void WebNotificationClient::cancel(Notification* notification) +{ +#if ENABLE(NOTIFICATIONS) + WebNotification *webNotification = m_notificationMap.get(notification).get(); + if (!webNotification) + return; + + [[m_webView _notificationProvider] cancelNotification:webNotification]; +#else + UNUSED_PARAM(notification); +#endif } -void WebNotificationClient::cancel(Notification*) +void WebNotificationClient::clearNotifications(ScriptExecutionContext* context) { - notImplemented(); +#if ENABLE(NOTIFICATIONS) + NotificationContextMap::iterator it = m_notificationContextMap.find(context); + if (it == m_notificationContextMap.end()) + return; + + Vector<RetainPtr<WebNotification> >& webNotifications = it->second; + NSMutableArray *nsIDs = [NSMutableArray array]; + size_t count = webNotifications.size(); + for (size_t i = 0; i < count; ++i) { + WebNotification *webNotification = webNotifications[i].get(); + [nsIDs addObject:[NSNumber numberWithUnsignedLongLong:[webNotification notificationID]]]; + m_notificationMap.remove(core(webNotification)); + } + + [[m_webView _notificationProvider] clearNotifications:nsIDs]; + m_notificationContextMap.remove(it); +#else + UNUSED_PARAM(context); +#endif } -void WebNotificationClient::notificationObjectDestroyed(WebCore::Notification*) +void WebNotificationClient::notificationObjectDestroyed(Notification* notification) { - notImplemented(); +#if ENABLE(NOTIFICATIONS) + RetainPtr<WebNotification> webNotification = m_notificationMap.take(notification); + if (!webNotification) + return; + + NotificationContextMap::iterator it = m_notificationContextMap.find(notification->scriptExecutionContext()); + ASSERT(it != m_notificationContextMap.end()); + size_t index = it->second.find(webNotification); + ASSERT(index != notFound); + it->second.remove(index); + if (it->second.isEmpty()) + m_notificationContextMap.remove(it); + + [[m_webView _notificationProvider] notificationDestroyed:webNotification.get()]; +#else + UNUSED_PARAM(notification); +#endif } void WebNotificationClient::notificationControllerDestroyed() { +#if ENABLE(NOTIFICATIONS) + [m_webView _notificationControllerDestroyed]; +#endif delete this; } -void WebNotificationClient::requestPermission(WebCore::ScriptExecutionContext*, PassRefPtr<WebCore::VoidCallback>) +void WebNotificationClient::requestPermission(ScriptExecutionContext* context, PassRefPtr<VoidCallback> callback) { - notImplemented(); +#if ENABLE(NOTIFICATIONS) + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + SEL selector = @selector(webView:decidePolicyForNotificationRequestFromOrigin:listener:); + if (![[m_webView UIDelegate] respondsToSelector:selector]) + return; + + WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:context->securityOrigin()]; + WebNotificationPolicyListener* listener = [[WebNotificationPolicyListener alloc] initWithCallback:callback]; + + CallUIDelegate(m_webView, selector, webOrigin, listener); + + [webOrigin release]; + [listener release]; + + END_BLOCK_OBJC_EXCEPTIONS; +#else + UNUSED_PARAM(context); + UNUSED_PARAM(callback); +#endif } -void WebNotificationClient::cancelRequestsForPermission(WebCore::ScriptExecutionContext*) +NotificationPresenter::Permission WebNotificationClient::checkPermission(ScriptExecutionContext* context) { - notImplemented(); +#if ENABLE(NOTIFICATIONS) + if (!context || !context->isDocument()) + return NotificationPresenter::PermissionDenied; + if (![[m_webView preferences] notificationsEnabled]) + return NotificationPresenter::PermissionDenied; + WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:context->securityOrigin()]; + WebNotificationPermission permission = [[m_webView _notificationProvider] policyForOrigin:webOrigin]; + [webOrigin release]; + switch (permission) { + case WebNotificationPermissionAllowed: + return NotificationPresenter::PermissionAllowed; + case WebNotificationPermissionDenied: + return NotificationPresenter::PermissionDenied; + case WebNotificationPermissionNotAllowed: + return NotificationPresenter::PermissionNotAllowed; + default: + return NotificationPresenter::PermissionNotAllowed; + } +#else + UNUSED_PARAM(context); + return NotificationPresenter::PermissionDenied; +#endif } -NotificationPresenter::Permission WebNotificationClient::checkPermission(WebCore::ScriptExecutionContext*) +#if ENABLE(NOTIFICATIONS) +@implementation WebNotificationPolicyListener +- (id)initWithCallback:(PassRefPtr<VoidCallback>)callback { - notImplemented(); - return NotificationPresenter::PermissionDenied; + if (!(self = [super init])) + return nil; + + ASSERT(callback); + _callback = callback; + return self; } + +- (void)allow +{ + _callback->handleEvent(); +} + +- (void)deny +{ + _callback->handleEvent(); +} + +@end +#endif diff --git a/Source/WebKit/mac/WebCoreSupport/WebPlatformStrategies.h b/Source/WebKit/mac/WebCoreSupport/WebPlatformStrategies.h index f1bd1a32c..4fde2b3b0 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebPlatformStrategies.h +++ b/Source/WebKit/mac/WebCoreSupport/WebPlatformStrategies.h @@ -27,11 +27,12 @@ #define WebPlatformStrategies_h #include <WebCore/CookiesStrategy.h> +#include <WebCore/PasteboardStrategy.h> #include <WebCore/PlatformStrategies.h> #include <WebCore/PluginStrategy.h> #include <WebCore/VisitedLinkStrategy.h> -class WebPlatformStrategies : public WebCore::PlatformStrategies, private WebCore::CookiesStrategy, private WebCore::PluginStrategy, private WebCore::VisitedLinkStrategy { +class WebPlatformStrategies : public WebCore::PlatformStrategies, private WebCore::CookiesStrategy, private WebCore::PluginStrategy, private WebCore::VisitedLinkStrategy, private WebCore::PasteboardStrategy { public: static void initialize(); @@ -42,6 +43,7 @@ private: virtual WebCore::CookiesStrategy* createCookiesStrategy() OVERRIDE; virtual WebCore::PluginStrategy* createPluginStrategy() OVERRIDE; virtual WebCore::VisitedLinkStrategy* createVisitedLinkStrategy() OVERRIDE; + virtual WebCore::PasteboardStrategy* createPasteboardStrategy() OVERRIDE; // WebCore::CookiesStrategy virtual void notifyCookiesChanged() OVERRIDE; @@ -53,6 +55,22 @@ private: // WebCore::VisitedLinkStrategy virtual bool isLinkVisited(WebCore::Page*, WebCore::LinkHash, const WebCore::KURL& baseURL, const WTF::AtomicString& attributeURL) OVERRIDE; virtual void addVisitedLink(WebCore::Page*, WebCore::LinkHash) OVERRIDE; + + // WebCore::PasteboardStrategy + virtual void getTypes(Vector<String>& types, const String& pasteboardName) OVERRIDE; + virtual PassRefPtr<WebCore::SharedBuffer> bufferForType(const String& pasteboardType, const String& pasteboardName) OVERRIDE; + virtual void getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName) OVERRIDE; + virtual String stringForType(const String& pasteboardType, const String& pasteboardName) OVERRIDE; + virtual int changeCount(const String& pasteboardName) OVERRIDE; + virtual String uniqueName() OVERRIDE; + virtual WebCore::Color color(const String& pasteboardName) OVERRIDE; + + virtual void copy(const String& fromPasteboard, const String& toPasteboard) OVERRIDE; + virtual void setTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName) OVERRIDE; + virtual void setBufferForType(PassRefPtr<WebCore::SharedBuffer>, const String& pasteboardType, const String& pasteboardName) OVERRIDE; + virtual void setPathnamesForType(const Vector<String>&, const String& pasteboardType, const String& pasteboardName) OVERRIDE; + virtual void setStringForType(const String&, const String& pasteboardType, const String& pasteboardName) OVERRIDE; + }; #endif // WebPlatformStrategies_h diff --git a/Source/WebKit/mac/WebCoreSupport/WebPlatformStrategies.mm b/Source/WebKit/mac/WebCoreSupport/WebPlatformStrategies.mm index d1a4d9560..fc3035048 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebPlatformStrategies.mm +++ b/Source/WebKit/mac/WebCoreSupport/WebPlatformStrategies.mm @@ -28,8 +28,10 @@ #import "WebPluginDatabase.h" #import "WebPluginPackage.h" #import <WebCore/BlockExceptions.h> +#import <WebCore/Color.h> #import <WebCore/Page.h> #import <WebCore/PageGroup.h> +#import <WebCore/PlatformPasteboard.h> using namespace WebCore; @@ -58,6 +60,11 @@ VisitedLinkStrategy* WebPlatformStrategies::createVisitedLinkStrategy() return this; } +PasteboardStrategy* WebPlatformStrategies::createPasteboardStrategy() +{ + return this; +} + void WebPlatformStrategies::notifyCookiesChanged() { } @@ -90,3 +97,63 @@ void WebPlatformStrategies::addVisitedLink(Page* page, LinkHash hash) { return page->group().addVisitedLinkHash(hash); } + +void WebPlatformStrategies::getTypes(Vector<String>& types, const String& pasteboardName) +{ + PlatformPasteboard(pasteboardName).getTypes(types); +} + +PassRefPtr<WebCore::SharedBuffer> WebPlatformStrategies::bufferForType(const String& pasteboardType, const String& pasteboardName) +{ + return PlatformPasteboard(pasteboardName).bufferForType(pasteboardType); +} + +void WebPlatformStrategies::getPathnamesForType(Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName) +{ + PlatformPasteboard(pasteboardName).getPathnamesForType(pathnames, pasteboardType); +} + +String WebPlatformStrategies::stringForType(const String& pasteboardType, const String& pasteboardName) +{ + return PlatformPasteboard(pasteboardName).stringForType(pasteboardType); +} + +void WebPlatformStrategies::copy(const String& fromPasteboard, const String& toPasteboard) +{ + PlatformPasteboard(toPasteboard).copy(fromPasteboard); +} + +int WebPlatformStrategies::changeCount(const String &pasteboardName) +{ + return PlatformPasteboard(pasteboardName).changeCount(); +} + +String WebPlatformStrategies::uniqueName() +{ + return PlatformPasteboard::uniqueName(); +} + +Color WebPlatformStrategies::color(const String& pasteboardName) +{ + return PlatformPasteboard(pasteboardName).color(); +} + +void WebPlatformStrategies::setTypes(const Vector<String>& pasteboardTypes, const String& pasteboardName) +{ + PlatformPasteboard(pasteboardName).setTypes(pasteboardTypes); +} + +void WebPlatformStrategies::setBufferForType(PassRefPtr<SharedBuffer> buffer, const String& pasteboardType, const String& pasteboardName) +{ + PlatformPasteboard(pasteboardName).setBufferForType(buffer, pasteboardType); +} + +void WebPlatformStrategies::setPathnamesForType(const Vector<String>& pathnames, const String& pasteboardType, const String& pasteboardName) +{ + PlatformPasteboard(pasteboardName).setPathnamesForType(pathnames, pasteboardType); +} + +void WebPlatformStrategies::setStringForType(const String& string, const String& pasteboardType, const String& pasteboardName) +{ + PlatformPasteboard(pasteboardName).setStringForType(string, pasteboardType); +} diff --git a/Source/WebKit/mac/WebCoreSupport/WebSecurityOrigin.mm b/Source/WebKit/mac/WebCoreSupport/WebSecurityOrigin.mm index 2373f8464..8f38fed43 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebSecurityOrigin.mm +++ b/Source/WebKit/mac/WebCoreSupport/WebSecurityOrigin.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2010, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -66,6 +66,11 @@ using namespace WebCore; return reinterpret_cast<SecurityOrigin*>(_private)->databaseIdentifier(); } +- (NSString *)stringValue +{ + return reinterpret_cast<SecurityOrigin*>(_private)->toString(); +} + // Deprecated. Use host instead. This needs to stay here until we ship a new Safari. - (NSString *)domain { diff --git a/Source/WebKit/mac/WebCoreSupport/WebSecurityOriginPrivate.h b/Source/WebKit/mac/WebCoreSupport/WebSecurityOriginPrivate.h index a784aba67..fae4c3382 100644 --- a/Source/WebKit/mac/WebCoreSupport/WebSecurityOriginPrivate.h +++ b/Source/WebKit/mac/WebCoreSupport/WebSecurityOriginPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2010, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -41,6 +41,7 @@ - (NSString *)host; - (NSString *)databaseIdentifier; +- (NSString *)stringValue; // Returns zero if the port is the default port for the protocol, non-zero otherwise. - (unsigned short)port; diff --git a/Source/WebKit/mac/WebKit.order b/Source/WebKit/mac/WebKit.order index 51b31e4a9..acd1a3755 100644 --- a/Source/WebKit/mac/WebKit.order +++ b/Source/WebKit/mac/WebKit.order @@ -2308,7 +2308,6 @@ __ZN3WTF6VectorINS_6RefPtrIN7WebCore14SecurityOriginEEELm0EED1Ev -[WebStorageManager syncLocalStorage] -[WebStorageManager deleteOrigin:] -[WebStorageManager diskUsageForOrigin:] --[WebFrame(WebPrivate) _pauseSVGAnimation:onSMILNode:atTime:] __ZN3WTF6RefPtrIN7WebCore7ArchiveEED1Ev __ZN3WTF10RefCountedIN7WebCore7ArchiveEE5derefEv -[WebDataSource webArchive] diff --git a/Source/WebKit/mac/WebView/WebFrame.mm b/Source/WebKit/mac/WebView/WebFrame.mm index 9c15fafef..24bb8f39c 100644 --- a/Source/WebKit/mac/WebView/WebFrame.mm +++ b/Source/WebKit/mac/WebView/WebFrame.mm @@ -87,8 +87,6 @@ #import <WebCore/ScriptValue.h> #import <WebCore/SecurityOrigin.h> #import <WebCore/SmartReplace.h> -#import <WebCore/SVGDocumentExtensions.h> -#import <WebCore/SVGSMILElement.h> #import <WebCore/TextIterator.h> #import <WebCore/ThreadCheck.h> #import <WebCore/TypingCommand.h> @@ -801,7 +799,8 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) { if (!_private->coreFrame) return; - _private->coreFrame->editor()->computeAndSetTypingStyle(core(style), undoAction); + // FIXME: We shouldn't have to create a copy here. + _private->coreFrame->editor()->computeAndSetTypingStyle(core(style)->copy().get(), undoAction); } - (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation @@ -992,29 +991,6 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) return controller->pauseTransitionAtTime(coreNode->renderer(), name, time); } -// Pause a given SVG animation on the target node at a specific time. -// This method is only intended to be used for testing the SVG animation system. -- (BOOL)_pauseSVGAnimation:(NSString*)elementId onSMILNode:(DOMNode *)node atTime:(NSTimeInterval)time -{ -#if ENABLE(SVG) - Frame* frame = core(self); - if (!frame) - return false; - - Document* document = frame->document(); - if (!document || !document->svgExtensions()) - return false; - - Node* coreNode = core(node); - if (!coreNode || !SVGSMILElement::isSMILElement(coreNode)) - return false; - - return document->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreNode), time); -#else - return false; -#endif -} - - (unsigned) _numberOfActiveAnimations { Frame* frame = core(self); @@ -1484,7 +1460,7 @@ static NSURL *createUniqueWebDataURL() if (!MIMEType) MIMEType = @"text/html"; - [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:nil]; + [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:[baseURL _webkit_URLFromURLOrPath] unreachableURL:nil]; } - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL diff --git a/Source/WebKit/mac/WebView/WebFramePrivate.h b/Source/WebKit/mac/WebView/WebFramePrivate.h index 98dbb706e..899ceeddf 100644 --- a/Source/WebKit/mac/WebView/WebFramePrivate.h +++ b/Source/WebKit/mac/WebView/WebFramePrivate.h @@ -104,10 +104,6 @@ typedef enum { - (BOOL)_pauseAnimation:(NSString*)name onNode:(DOMNode *)node atTime:(NSTimeInterval)time; - (BOOL)_pauseTransitionOfProperty:(NSString*)name onNode:(DOMNode*)node atTime:(NSTimeInterval)time; -// Pause a given SVG animation on the target node at a specific time. -// This method is only intended to be used for testing the SVG animation system. -- (BOOL)_pauseSVGAnimation:(NSString*)elementId onSMILNode:(DOMNode *)node atTime:(NSTimeInterval)time; - // Returns the total number of currently running animations (includes both CSS transitions and CSS animations). - (unsigned)_numberOfActiveAnimations; diff --git a/Source/WebKit/mac/WebView/WebHTMLView.mm b/Source/WebKit/mac/WebView/WebHTMLView.mm index 66f7b3aaf..7052fca0b 100644 --- a/Source/WebKit/mac/WebView/WebHTMLView.mm +++ b/Source/WebKit/mac/WebView/WebHTMLView.mm @@ -4352,14 +4352,10 @@ static PassRefPtr<KeyboardEvent> currentKeyboardEvent(Frame* coreFrame) - (void)_applyStyleToSelection:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction { - if (Frame* coreFrame = core([self _frame])) - coreFrame->editor()->applyStyleToSelection(core(style), undoAction); -} - -- (void)_applyParagraphStyleToSelection:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction -{ - if (Frame* coreFrame = core([self _frame])) - coreFrame->editor()->applyParagraphStyleToSelection(core(style), undoAction); + if (Frame* coreFrame = core([self _frame])) { + // FIXME: We shouldn't have to make a copy here. We want callers of this function to work directly with StylePropertySet eventually. + coreFrame->editor()->applyStyleToSelection(core(style)->copy().get(), undoAction); + } } - (BOOL)_handleStyleKeyEquivalent:(NSEvent *)event @@ -4657,9 +4653,13 @@ static PassRefPtr<KeyboardEvent> currentKeyboardEvent(Frame* coreFrame) { DOMCSSStyleDeclaration *style = [self _styleFromColorPanelWithSelector:selector]; WebView *webView = [self _webView]; - if ([[webView _editingDelegateForwarder] webView:webView shouldApplyStyle:style toElementsInDOMRange:range]) - if (Frame* coreFrame = core([self _frame])) - coreFrame->editor()->applyStyle(core(style), [self _undoActionFromColorPanelWithSelector:selector]); + if ([[webView _editingDelegateForwarder] webView:webView shouldApplyStyle:style toElementsInDOMRange:range]) { + if (Frame* coreFrame = core([self _frame])) { + // FIXME: We shouldn't have to make a copy here. + coreFrame->editor()->applyStyle(core(style)->copy().get(), [self _undoActionFromColorPanelWithSelector:selector]); + } + } + } - (void)changeDocumentBackgroundColor:(id)sender diff --git a/Source/WebKit/mac/WebView/WebNotification.h b/Source/WebKit/mac/WebView/WebNotification.h new file mode 100644 index 000000000..c04b2ad07 --- /dev/null +++ b/Source/WebKit/mac/WebView/WebNotification.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. + */ + +@class WebNotificationPrivate; +@class WebSecurityOrigin; + +@interface WebNotification : NSObject +{ + WebNotificationPrivate *_private; +} + +- (NSString *)title; +- (NSString *)body; +- (WebSecurityOrigin *)origin; +- (uint64_t)notificationID; + +- (void)dispatchShowEvent; +- (void)dispatchCloseEvent; +- (void)dispatchClickEvent; +- (void)dispatchErrorEvent; + +@end diff --git a/Source/WebKit/mac/WebView/WebNotification.mm b/Source/WebKit/mac/WebView/WebNotification.mm new file mode 100644 index 000000000..bbd0248f6 --- /dev/null +++ b/Source/WebKit/mac/WebView/WebNotification.mm @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2012 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. + */ + +#import "WebNotification.h" + +#import "WebNotificationInternal.h" + +#if ENABLE(NOTIFICATIONS) +#import "WebSecurityOriginInternal.h" +#import <WebCore/Notification.h> +#import <WebCore/ScriptExecutionContext.h> +#import <wtf/RefPtr.h> + +using namespace WebCore; +#endif + +OBJC_CLASS WebNotificationInternal; + +@interface WebNotificationPrivate : NSObject +{ +@public +#if ENABLE(NOTIFICATIONS) + RefPtr<Notification> _internal; + uint64_t _notificationID; +#endif +} +@end + +@implementation WebNotificationPrivate +@end + +#if ENABLE(NOTIFICATIONS) +@implementation WebNotification (WebNotificationInternal) +Notification* core(WebNotification *notification) +{ + if (!notification->_private) + return 0; + return notification->_private->_internal.get(); +} + +- (id)initWithCoreNotification:(Notification*)coreNotification notificationID:(uint64_t)notificationID +{ + if (!(self = [super init])) + return nil; + _private = [[WebNotificationPrivate alloc] init]; + _private->_internal = coreNotification; + _private->_notificationID = notificationID; + return self; +} +@end +#endif + +@implementation WebNotification +- (id)init +{ + return nil; +} + +- (NSString *)title +{ +#if ENABLE(NOTIFICATIONS) + ASSERT(core(self)); + return core(self)->contents().title; +#else + return nil; +#endif +} + +- (NSString *)body +{ +#if ENABLE(NOTIFICATIONS) + ASSERT(core(self)); + return core(self)->contents().body; +#else + return nil; +#endif +} + +- (WebSecurityOrigin *)origin +{ +#if ENABLE(NOTIFICATIONS) + ASSERT(core(self)); + return [[[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:core(self)->scriptExecutionContext()->securityOrigin()] autorelease]; +#else + return nil; +#endif +} + +- (uint64_t)notificationID +{ +#if ENABLE(NOTIFICATIONS) + ASSERT(core(self)); + return _private->_notificationID; +#else + return 0; +#endif +} + +- (void)dispatchShowEvent +{ +#if ENABLE(NOTIFICATIONS) + ASSERT(core(self)); + core(self)->dispatchShowEvent(); +#endif +} + +- (void)dispatchCloseEvent +{ +#if ENABLE(NOTIFICATIONS) + ASSERT(core(self)); + core(self)->dispatchCloseEvent(); +#endif +} + +- (void)dispatchClickEvent +{ +#if ENABLE(NOTIFICATIONS) + ASSERT(core(self)); + core(self)->dispatchClickEvent(); +#endif +} + +- (void)dispatchErrorEvent +{ +#if ENABLE(NOTIFICATIONS) + ASSERT(core(self)); + core(self)->dispatchErrorEvent(); +#endif +} + +@end + diff --git a/Source/WebKit/mac/WebView/WebNotificationInternal.h b/Source/WebKit/mac/WebView/WebNotificationInternal.h new file mode 100644 index 000000000..b624069d9 --- /dev/null +++ b/Source/WebKit/mac/WebView/WebNotificationInternal.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. + */ + +#import "WebNotification.h" + +#if ENABLE(NOTIFICATIONS) + +namespace WebCore { +class Notification; +} + +WebCore::Notification* core(WebNotification *); + +@interface WebNotification (WebNotificationInternal) +- (id)initWithCoreNotification:(WebCore::Notification*)coreNotification notificationID:(uint64_t)notificationID; +@end + +#endif diff --git a/Source/WebKit/mac/WebView/WebPreferenceKeysPrivate.h b/Source/WebKit/mac/WebView/WebPreferenceKeysPrivate.h index 20e42ab3d..261a30e56 100644 --- a/Source/WebKit/mac/WebView/WebPreferenceKeysPrivate.h +++ b/Source/WebKit/mac/WebView/WebPreferenceKeysPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2005, 2012 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -95,6 +95,7 @@ #define WebKitCanvasUsesAcceleratedDrawingPreferenceKey @"WebKitCanvasUsesAcceleratedDrawing" #define WebKitAcceleratedCompositingEnabledPreferenceKey @"WebKitAcceleratedCompositingEnabled" #define WebKitCSSCustomFilterEnabledPreferenceKey @"WebKitCSSCustomFilterEnabled" +#define WebKitCSSRegionsEnabledPreferenceKey @"WebKitCSSRegionsEnabled" #define WebKitShowDebugBordersPreferenceKey @"WebKitShowDebugBorders" #define WebKitShowRepaintCounterPreferenceKey @"WebKitShowRepaintCounter" #define WebKitWebAudioEnabledPreferenceKey @"WebKitWebAudioEnabled" @@ -116,6 +117,8 @@ #define WebKitShouldDisplaySubtitlesPreferenceKey @"WebKitShouldDisplaySubtitles" #define WebKitShouldDisplayCaptionsPreferenceKey @"WebKitShouldDisplayCaptions" #define WebKitShouldDisplayTextDescriptionsPreferenceKey @"WebKitShouldDisplayTextDescriptions" +#define WebKitNotificationsEnabledKey @"WebKitNotificationsEnabled" +#define WebKitSuppressesIncrementalRenderingKey @"WebKitSuppressesIncrementalRendering" // These are private both because callers should be using the cover methods and because the // cover methods themselves are private. @@ -130,7 +133,6 @@ #define WebKitTextDirectionSubmenuInclusionBehaviorPreferenceKey @"WebKitTextDirectionSubmenuInclusionBehaviorPreferenceKey" #define WebKitEditingBehaviorPreferenceKey @"WebKitEditingBehavior" #define WebKitUsePreHTML5ParserQuirksKey @"WebKitUsePreHTML5ParserQuirks" -#define WebKitSuppressIncrementalRenderingKey @"WebKitSuppressIncrementalRendering" #define WebKitBackspaceKeyNavigationEnabledKey @"WebKitBackspaceKeyNavigationEnabled" // CoreGraphics deferred updates are disabled if WebKitEnableCoalescedUpdatesPreferenceKey is set diff --git a/Source/WebKit/mac/WebView/WebPreferences.h b/Source/WebKit/mac/WebView/WebPreferences.h index 80cc9355a..6e01709f0 100644 --- a/Source/WebKit/mac/WebView/WebPreferences.h +++ b/Source/WebKit/mac/WebView/WebPreferences.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2004, 2005 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2012 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -431,4 +431,17 @@ caching behavior. */ - (WebCacheModel)cacheModel; +/*! + @method setSuppressesIncrementalRendering: + @param suppressesIncrementalRendering YES to suppress incremental rendering; + NO otherwise. +*/ +- (void)setSuppressesIncrementalRendering:(BOOL)suppressesIncrementalRendering; + +/*! + @method suppressesIncrementalRendering + @result YES if the WebView suppresses incremental rendering; NO otherwise. +*/ +- (BOOL)suppressesIncrementalRendering; + @end diff --git a/Source/WebKit/mac/WebView/WebPreferences.mm b/Source/WebKit/mac/WebView/WebPreferences.mm index f49df5473..ed23910a9 100644 --- a/Source/WebKit/mac/WebView/WebPreferences.mm +++ b/Source/WebKit/mac/WebView/WebPreferences.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006, 2007, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2007, 2011, 2012 Apple Inc. All rights reserved. * (C) 2006 Graham Dennis (graham.dennis@gmail.com) * * Redistribution and use in source and binary forms, with or without @@ -369,6 +369,7 @@ static WebCacheModel cacheModelForMainBundle(void) [NSNumber numberWithBool:YES], WebKitAcceleratedCompositingEnabledPreferenceKey, // CSS Shaders also need WebGL enabled (which is disabled by default), so we can keep it enabled for now. [NSNumber numberWithBool:YES], WebKitCSSCustomFilterEnabledPreferenceKey, + [NSNumber numberWithBool:YES], WebKitCSSRegionsEnabledPreferenceKey, [NSNumber numberWithBool:NO], WebKitAcceleratedDrawingEnabledPreferenceKey, [NSNumber numberWithBool:NO], WebKitCanvasUsesAcceleratedDrawingPreferenceKey, [NSNumber numberWithBool:NO], WebKitShowDebugBordersPreferenceKey, @@ -384,15 +385,16 @@ static WebCacheModel cacheModelForMainBundle(void) [NSNumber numberWithBool:YES], WebKitHyperlinkAuditingEnabledPreferenceKey, [NSNumber numberWithBool:NO], WebKitUsePreHTML5ParserQuirksKey, [NSNumber numberWithBool:YES], WebKitAVFoundationEnabledKey, - [NSNumber numberWithBool:YES], WebKitHixie76WebSocketProtocolEnabledKey, + [NSNumber numberWithBool:NO], WebKitHixie76WebSocketProtocolEnabledKey, [NSNumber numberWithBool:NO], WebKitMediaPlaybackRequiresUserGesturePreferenceKey, [NSNumber numberWithBool:YES], WebKitMediaPlaybackAllowsInlinePreferenceKey, [NSNumber numberWithBool:NO], WebKitWebAudioEnabledPreferenceKey, - [NSNumber numberWithBool:NO], WebKitSuppressIncrementalRenderingKey, + [NSNumber numberWithBool:NO], WebKitSuppressesIncrementalRenderingKey, [NSNumber numberWithBool:YES], WebKitBackspaceKeyNavigationEnabledKey, [NSNumber numberWithBool:NO], WebKitShouldDisplaySubtitlesPreferenceKey, [NSNumber numberWithBool:NO], WebKitShouldDisplayCaptionsPreferenceKey, [NSNumber numberWithBool:NO], WebKitShouldDisplayTextDescriptionsPreferenceKey, + [NSNumber numberWithBool:YES], WebKitNotificationsEnabledKey, [NSNumber numberWithLongLong:ApplicationCacheStorage::noQuota()], WebKitApplicationCacheTotalQuota, [NSNumber numberWithLongLong:ApplicationCacheStorage::noQuota()], WebKitApplicationCacheDefaultOriginQuota, @@ -806,6 +808,17 @@ static WebCacheModel cacheModelForMainBundle(void) return [self _integerValueForKey:WebKitCacheModelPreferenceKey]; } + +- (void)setSuppressesIncrementalRendering:(BOOL)suppressesIncrementalRendering +{ + [self _setBoolValue:suppressesIncrementalRendering forKey:WebKitSuppressesIncrementalRenderingKey]; +} + +- (BOOL)suppressesIncrementalRendering +{ + return [self _boolValueForKey:WebKitSuppressesIncrementalRenderingKey]; +} + @end @implementation WebPreferences (WebPrivate) @@ -1335,6 +1348,16 @@ static NSString *classIBCreatorID = nil; [self _setBoolValue:enabled forKey:WebKitCSSCustomFilterEnabledPreferenceKey]; } +- (BOOL)cssRegionsEnabled +{ + return [self _boolValueForKey:WebKitCSSRegionsEnabledPreferenceKey]; +} + +- (void)setCSSRegionsEnabled:(BOOL)enabled +{ + [self _setBoolValue:enabled forKey:WebKitCSSRegionsEnabledPreferenceKey]; +} + - (BOOL)showDebugBorders { return [self _boolValueForKey:WebKitShowDebugBordersPreferenceKey]; @@ -1583,12 +1606,12 @@ static NSString *classIBCreatorID = nil; - (void)setSuppressIncrementalRendering:(BOOL)flag { - [self _setBoolValue:flag forKey:WebKitSuppressIncrementalRenderingKey]; + [self _setBoolValue:flag forKey:WebKitSuppressesIncrementalRenderingKey]; } - (BOOL)suppressIncrementalRendering { - return [self _boolValueForKey:WebKitSuppressIncrementalRenderingKey]; + return [self _boolValueForKey:WebKitSuppressesIncrementalRenderingKey]; } - (void)setBackspaceKeyNavigationEnabled:(BOOL)flag @@ -1631,6 +1654,16 @@ static NSString *classIBCreatorID = nil; return [self _boolValueForKey:WebKitShouldDisplayTextDescriptionsPreferenceKey]; } +- (void)setNotificationsEnabled:(BOOL)flag +{ + [self _setBoolValue:flag forKey:WebKitNotificationsEnabledKey]; +} + +- (BOOL)notificationsEnabled +{ + return [self _boolValueForKey:WebKitNotificationsEnabledKey]; +} + @end @implementation WebPreferences (WebInternal) diff --git a/Source/WebKit/mac/WebView/WebPreferencesPrivate.h b/Source/WebKit/mac/WebView/WebPreferencesPrivate.h index 305434ffb..29a8be125 100644 --- a/Source/WebKit/mac/WebView/WebPreferencesPrivate.h +++ b/Source/WebKit/mac/WebView/WebPreferencesPrivate.h @@ -189,6 +189,9 @@ extern NSString *WebPreferencesChangedInternalNotification; - (BOOL)cssCustomFilterEnabled; - (void)setCSSCustomFilterEnabled:(BOOL)enabled; +- (BOOL)cssRegionsEnabled; +- (void)setCSSRegionsEnabled:(BOOL)enabled; + - (BOOL)showDebugBorders; - (void)setShowDebugBorders:(BOOL)show; @@ -271,6 +274,7 @@ extern NSString *WebPreferencesChangedInternalNotification; - (void)setHixie76WebSocketProtocolEnabled:(BOOL)flag; - (BOOL)isHixie76WebSocketProtocolEnabled; +// Deprecated. You should use [setS|s]uppressesIncrementalRendering in WebPreferences.h instead. - (void)setSuppressIncrementalRendering:(BOOL)flag; - (BOOL)suppressIncrementalRendering; @@ -286,4 +290,7 @@ extern NSString *WebPreferencesChangedInternalNotification; - (void)setShouldDisplayTextDescriptions:(BOOL)flag; - (BOOL)shouldDisplayTextDescriptions; +- (void)setNotificationsEnabled:(BOOL)flag; +- (BOOL)notificationsEnabled; + @end diff --git a/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h b/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h index 9c98fdfcc..9f1801961 100644 --- a/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h +++ b/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -117,9 +117,11 @@ extern NSString *WebConsoleMessageWarningMessageLevel; extern NSString *WebConsoleMessageErrorMessageLevel; extern NSString *WebConsoleMessageDebugMessageLevel; +@class DOMElement; +@class DOMNode; @class WebSecurityOrigin; -@protocol WebGeolocationPolicyListener <NSObject> +@protocol WebAllowDenyPolicyListener <NSObject> - (void)allow; - (void)deny; @end @@ -223,7 +225,8 @@ extern NSString *WebConsoleMessageDebugMessageLevel; */ - (void)webView:(WebView *)webView decidePolicyForGeolocationRequestFromOrigin:(WebSecurityOrigin *)origin frame:(WebFrame *)frame - listener:(id<WebGeolocationPolicyListener>)listener; + listener:(id<WebAllowDenyPolicyListener>)listener; +- (void)webView:(WebView *)webView decidePolicyForNotificationRequestFromOrigin:(WebSecurityOrigin *)origin listener:(id<WebAllowDenyPolicyListener>)listener; - (void)webView:(WebView *)sender elementDidFocusNode:(DOMNode *)node; - (void)webView:(WebView *)sender elementDidBlurNode:(DOMNode *)node; diff --git a/Source/WebKit/mac/WebView/WebView.mm b/Source/WebKit/mac/WebView/WebView.mm index 4525cba9f..9b722026e 100644 --- a/Source/WebKit/mac/WebView/WebView.mm +++ b/Source/WebKit/mac/WebView/WebView.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2005-2012 Apple Inc. All rights reserved. * Copyright (C) 2006 David Smith (catfish.man@gmail.com) * Copyright (C) 2010 Igalia S.L * @@ -742,13 +742,13 @@ static NSString *leakOutlookQuirksUserScriptContents() #if ENABLE(CLIENT_BASED_GEOLOCATION) pageClients.geolocationClient = new WebGeolocationClient(self); #endif + _private->page = new Page(pageClients); #if ENABLE(NOTIFICATIONS) - pageClients.notificationClient = new WebNotificationClient(self); + WebCore::provideNotification(_private->page, new WebNotificationClient(self)); #endif #if ENABLE(DEVICE_ORIENTATION) - pageClients.deviceOrientationClient = new WebDeviceOrientationClient(self); + WebCore::provideDeviceOrientationTo(_private->page, new WebDeviceOrientationClient(self)); #endif - _private->page = new Page(pageClients); _private->page->setCanStartMedia([self window]); _private->page->settings()->setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]); @@ -1322,6 +1322,13 @@ static bool fastDocumentTeardownEnabled() return needsQuirk; } +- (BOOL)_needsIsLoadingInAPISenseQuirk +{ + static BOOL needsQuirk = WKAppVersionCheckLessThan(@"com.apple.iAdProducer", -1, 2.1); + + return needsQuirk; +} + - (BOOL)_needsKeyboardEventDisambiguationQuirks { static BOOL needsQuirks = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH) && !applicationIsSafari(); @@ -1474,6 +1481,7 @@ static bool needsSelfRetainWhileLoadingQuirk() #if ENABLE(CSS_SHADERS) settings->setCSSCustomFilterEnabled([preferences cssCustomFilterEnabled]); #endif + settings->setCSSRegionsEnabled([preferences cssRegionsEnabled]); #if ENABLE(FULLSCREEN_API) settings->setFullScreenEnabled([preferences fullScreenEnabled]); #endif @@ -1499,7 +1507,7 @@ static bool needsSelfRetainWhileLoadingQuirk() #endif settings->setMediaPlaybackRequiresUserGesture([preferences mediaPlaybackRequiresUserGesture]); settings->setMediaPlaybackAllowsInline([preferences mediaPlaybackAllowsInline]); - settings->setSuppressIncrementalRendering([preferences suppressIncrementalRendering]); + settings->setSuppressesIncrementalRendering([preferences suppressesIncrementalRendering]); settings->setBackspaceKeyNavigationEnabled([preferences backspaceKeyNavigationEnabled]); settings->setMockScrollbarsEnabled([preferences mockScrollbarsEnabled]); @@ -1509,6 +1517,8 @@ static bool needsSelfRetainWhileLoadingQuirk() settings->setShouldDisplayTextDescriptions([preferences shouldDisplayTextDescriptions]); #endif + settings->setNeedsIsLoadingInAPISenseQuirk([self _needsIsLoadingInAPISenseQuirk]); + // Application Cache Preferences are stored on the global cache storage manager, not in Settings. [WebApplicationCache setDefaultOriginQuota:[preferences applicationCacheDefaultOriginQuota]]; @@ -5516,8 +5526,9 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue jsValu // change the API to allow this. WebFrame *webFrame = [self _selectedOrMainFrame]; Frame* coreFrame = core(webFrame); + // FIXME: We shouldn't have to make a copy here. if (coreFrame) - coreFrame->editor()->applyStyle(core(style)); + coreFrame->editor()->applyStyle(core(style)->copy().get()); } @end @@ -6401,6 +6412,43 @@ static void glibContextIterationCallback(CFRunLoopObserverRef, CFRunLoopActivity @end +@implementation WebView (WebViewNotification) +- (void)_setNotificationProvider:(id<WebNotificationProvider>)notificationProvider +{ + if (_private) { + _private->_notificationProvider = notificationProvider; + [_private->_notificationProvider registerWebView:self]; + } +} + +- (void)_notificationControllerDestroyed +{ + [[self _notificationProvider] unregisterWebView:self]; +} + +- (id<WebNotificationProvider>)_notificationProvider +{ + if (_private) + return _private->_notificationProvider; + return nil; +} + +- (void)_notificationDidShow:(uint64_t)notificationID +{ + [[self _notificationProvider] webView:self didShowNotification:notificationID]; +} + +- (void)_notificationDidClick:(uint64_t)notificationID +{ + [[self _notificationProvider] webView:self didClickNotification:notificationID]; +} + +- (void)_notificationsDidClose:(NSArray *)notificationIDs +{ + [[self _notificationProvider] webView:self didCloseNotifications:notificationIDs]; +} +@end + @implementation WebView (WebViewPrivateStyleInfo) - (JSValueRef)_computedStyleIncludingVisitedInfo:(JSContextRef)context forElement:(JSValueRef)value @@ -6414,7 +6462,7 @@ static void glibContextIterationCallback(CFRunLoopObserverRef, CFRunLoopActivity return JSValueMakeUndefined(context); JSElement* jsElement = static_cast<JSElement*>(asObject(jsValue)); Element* element = jsElement->impl(); - RefPtr<CSSComputedStyleDeclaration> style = computedStyle(element, true); + RefPtr<CSSComputedStyleDeclaration> style = CSSComputedStyleDeclaration::create(element, true); return toRef(exec, toJS(exec, jsElement->globalObject(), style.get())); } diff --git a/Source/WebKit/mac/WebView/WebViewData.h b/Source/WebKit/mac/WebView/WebViewData.h index 665cb9175..ea2bfcf60 100644 --- a/Source/WebKit/mac/WebView/WebViewData.h +++ b/Source/WebKit/mac/WebView/WebViewData.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved. * Copyright (C) 2010 Igalia S.L * * Redistribution and use in source and binary forms, with or without @@ -50,6 +50,7 @@ namespace WebCore { @protocol WebFormDelegate; @protocol WebDeviceOrientationProvider; @protocol WebGeolocationProvider; +@protocol WebNotificationProvider; #if ENABLE(VIDEO) @class WebVideoFullscreenController; #endif @@ -191,6 +192,7 @@ private: #endif id<WebGeolocationProvider> _geolocationProvider; id<WebDeviceOrientationProvider> m_deviceOrientationProvider; + id<WebNotificationProvider> _notificationProvider; RefPtr<WebCore::HistoryItem> _globalHistoryItem; diff --git a/Source/WebKit/mac/WebView/WebViewPrivate.h b/Source/WebKit/mac/WebView/WebViewPrivate.h index cd92f31e5..e0fee81d1 100644 --- a/Source/WebKit/mac/WebView/WebViewPrivate.h +++ b/Source/WebKit/mac/WebView/WebViewPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2005-2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -39,8 +39,10 @@ @class WebDeviceOrientation; @class WebGeolocationPosition; @class WebInspector; +@class WebNotification; @class WebPreferences; @class WebScriptWorld; +@class WebSecurityOrigin; @class WebTextIterator; @protocol WebDeviceOrientationProvider; @@ -104,6 +106,13 @@ typedef enum { WebPaginationModeVertical, } WebPaginationMode; +// This needs to be in sync with WebCore::NotificationPresenter::Permission +typedef enum { + WebNotificationPermissionAllowed, + WebNotificationPermissionNotAllowed, + WebNotificationPermissionDenied +} WebNotificationPermission; + @interface WebController : NSTreeController { IBOutlet WebView *webView; } @@ -701,6 +710,21 @@ Could be worth adding to the API. - (WebGeolocationPosition *)lastPosition; @end +@protocol WebNotificationProvider +- (void)registerWebView:(WebView *)webView; +- (void)unregisterWebView:(WebView *)webView; + +- (void)showNotification:(WebNotification *)notification fromWebView:(WebView *)webView; +- (void)cancelNotification:(WebNotification *)notification; +- (void)notificationDestroyed:(WebNotification *)notification; +- (void)clearNotifications:(NSArray *)notificationIDs; +- (WebNotificationPermission)policyForOrigin:(WebSecurityOrigin *)origin; + +- (void)webView:(WebView *)webView didShowNotification:(uint64_t)notificationID; +- (void)webView:(WebView *)webView didClickNotification:(uint64_t)notificationID; +- (void)webView:(WebView *)webView didCloseNotifications:(NSArray *)notificationIDs; +@end + @interface WebView (WebViewGeolocation) - (void)_setGeolocationProvider:(id<WebGeolocationProvider>)locationProvider; - (id<WebGeolocationProvider>)_geolocationProvider; @@ -709,6 +733,16 @@ Could be worth adding to the API. - (void)_geolocationDidFailWithError:(NSError *)error; @end +@interface WebView (WebViewNotification) +- (void)_setNotificationProvider:(id<WebNotificationProvider>)notificationProvider; +- (id<WebNotificationProvider>)_notificationProvider; +- (void)_notificationControllerDestroyed; + +- (void)_notificationDidShow:(uint64_t)notificationID; +- (void)_notificationDidClick:(uint64_t)notificationID; +- (void)_notificationsDidClose:(NSArray *)notificationIDs; +@end + @interface WebView (WebViewPrivateStyleInfo) - (JSValueRef)_computedStyleIncludingVisitedInfo:(JSContextRef)context forElement:(JSValueRef)value; @end diff --git a/Source/WebKit/qt/Api/qgraphicswebview.cpp b/Source/WebKit/qt/Api/qgraphicswebview.cpp index c1eb5293a..3f6fe1471 100644 --- a/Source/WebKit/qt/Api/qgraphicswebview.cpp +++ b/Source/WebKit/qt/Api/qgraphicswebview.cpp @@ -288,13 +288,13 @@ void QGraphicsWebView::paint(QPainter* painter, const QStyleOptionGraphicsItem* #if USE(TILED_BACKING_STORE) if (WebCore::TiledBackingStore* backingStore = QWebFramePrivate::core(page()->mainFrame())->tiledBackingStore()) { // FIXME: We should set the backing store viewport earlier than in paint - backingStore->adjustVisibleRect(); + backingStore->coverWithTilesIfNeeded(); // QWebFrame::render is a public API, bypass it for tiled rendering so behavior does not need to change. - WebCore::GraphicsContext context(painter); + WebCore::GraphicsContext context(painter); page()->mainFrame()->d->renderFromTiledBackingStore(&context, option->exposedRect.toAlignedRect()); painter->setRenderHints(oldHints); return; - } + } #endif #if USE(ACCELERATED_COMPOSITING) && !USE(TEXTURE_MAPPER) page()->mainFrame()->render(painter, d->overlay() ? QWebFrame::ContentsLayer : QWebFrame::AllLayers, option->exposedRect.toAlignedRect()); @@ -312,7 +312,11 @@ bool QGraphicsWebView::sceneEvent(QEvent* event) if (d->page && (event->type() == QEvent::TouchBegin || event->type() == QEvent::TouchEnd - || event->type() == QEvent::TouchUpdate)) { + || event->type() == QEvent::TouchUpdate +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + || event->type() == QEvent::TouchCancel +#endif + )) { d->page->event(event); // Always return true so that we'll receive also TouchUpdate and TouchEnd events diff --git a/Source/WebKit/qt/Api/qwebelement.cpp b/Source/WebKit/qt/Api/qwebelement.cpp index 178c70e5b..40c69f4bf 100644 --- a/Source/WebKit/qt/Api/qwebelement.cpp +++ b/Source/WebKit/qt/Api/qwebelement.cpp @@ -882,7 +882,7 @@ QString QWebElement::styleProperty(const QString &name, StyleResolveStrategy str int propID = cssPropertyID(name); - RefPtr<CSSComputedStyleDeclaration> style = computedStyle(m_element, true); + RefPtr<CSSComputedStyleDeclaration> style = CSSComputedStyleDeclaration::create(m_element, true); if (!propID || !style) return QString(); diff --git a/Source/WebKit/qt/Api/qwebframe.cpp b/Source/WebKit/qt/Api/qwebframe.cpp index 39b9d20d4..211f0ef20 100644 --- a/Source/WebKit/qt/Api/qwebframe.cpp +++ b/Source/WebKit/qt/Api/qwebframe.cpp @@ -104,7 +104,7 @@ #endif #if USE(TEXTURE_MAPPER) #include "texmap/TextureMapper.h" -#include "texmap/TextureMapperNode.h" +#include "texmap/TextureMapperLayer.h" #endif #include "wtf/HashMap.h" #include <QMultiMap> @@ -331,7 +331,7 @@ void QWebFramePrivate::renderFromTiledBackingStore(GraphicsContext* context, con #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) void QWebFramePrivate::renderCompositedLayers(GraphicsContext* context, const IntRect& clip) { - if (!rootTextureMapperNode || !textureMapper) + if (!rootTextureMapperLayer || !textureMapper) return; textureMapper->setGraphicsContext(context); @@ -345,11 +345,11 @@ void QWebFramePrivate::renderCompositedLayers(GraphicsContext* context, const In 0, 0, 1, 0, transform.m31(), transform.m32(), 0, transform.m33() ); - rootTextureMapperNode->setTransform(matrix); - rootTextureMapperNode->setOpacity(painter->opacity()); + rootTextureMapperLayer->setTransform(matrix); + rootTextureMapperLayer->setOpacity(painter->opacity()); textureMapper->beginPainting(); textureMapper->beginClip(matrix, clip); - rootTextureMapperNode->paint(); + rootTextureMapperLayer->paint(); textureMapper->endClip(); textureMapper->endPainting(); } diff --git a/Source/WebKit/qt/Api/qwebframe.h b/Source/WebKit/qt/Api/qwebframe.h index 35fce4beb..ff157771f 100644 --- a/Source/WebKit/qt/Api/qwebframe.h +++ b/Source/WebKit/qt/Api/qwebframe.h @@ -60,7 +60,7 @@ namespace WebCore { class WidgetPrivate; class FrameLoaderClientQt; class ChromeClientQt; - class TextureMapperNodeClientQt; + class TextureMapperLayerClientQt; } class QWebFrameData; class QWebHitTestResultPrivate; @@ -234,7 +234,7 @@ private: friend class WebCore::WidgetPrivate; friend class WebCore::FrameLoaderClientQt; friend class WebCore::ChromeClientQt; - friend class WebCore::TextureMapperNodeClientQt; + friend class WebCore::TextureMapperLayerClientQt; QWebFramePrivate *d; Q_PRIVATE_SLOT(d, void _q_orientationChanged()) }; diff --git a/Source/WebKit/qt/Api/qwebframe_p.h b/Source/WebKit/qt/Api/qwebframe_p.h index 1dba6a59e..4ab7b9700 100644 --- a/Source/WebKit/qt/Api/qwebframe_p.h +++ b/Source/WebKit/qt/Api/qwebframe_p.h @@ -49,7 +49,7 @@ namespace WebCore { class FrameView; class HTMLFrameOwnerElement; class Scrollbar; - class TextureMapperNode; + class TextureMapperLayer; } class QWebPage; @@ -85,7 +85,7 @@ public: , marginWidth(-1) , marginHeight(-1) #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) - , rootTextureMapperNode(0) + , rootTextureMapperLayer(0) #endif {} void init(QWebFrame* qframe, QWebFrameData* frameData); @@ -125,7 +125,7 @@ public: int marginWidth; int marginHeight; #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) - WebCore::TextureMapperNode* rootTextureMapperNode; + WebCore::TextureMapperLayer* rootTextureMapperLayer; OwnPtr<WebCore::TextureMapper> textureMapper; #endif diff --git a/Source/WebKit/qt/Api/qwebpage.cpp b/Source/WebKit/qt/Api/qwebpage.cpp index f94d44589..898899bf5 100644 --- a/Source/WebKit/qt/Api/qwebpage.cpp +++ b/Source/WebKit/qt/Api/qwebpage.cpp @@ -105,6 +105,7 @@ #include "RenderThemeQt.h" #include "SchemeRegistry.h" #include "Scrollbar.h" +#include "ScrollbarTheme.h" #include "SecurityOrigin.h" #include "Settings.h" #if defined Q_OS_WIN32 @@ -112,9 +113,11 @@ #endif // Q_OS_WIN32 #include "TextIterator.h" #include "UtilsQt.h" +#include "WebEventConversion.h" #include "WindowFeatures.h" #include "WorkerThread.h" +#include <QAction> #include <QApplication> #include <QBasicTimer> #include <QBitArray> @@ -126,6 +129,7 @@ #include <QDropEvent> #include <QFileDialog> #include <QInputDialog> +#include <QMenu> #include <QMessageBox> #include <QNetworkProxy> #include <QUndoStack> @@ -322,24 +326,23 @@ QWebPagePrivate::QWebPagePrivate(QWebPage *qq) pageClients.editorClient = new EditorClientQt(q); pageClients.dragClient = new DragClientQt(q); pageClients.inspectorClient = new InspectorClientQt(q); -#if ENABLE(DEVICE_ORIENTATION) - if (useMock) - pageClients.deviceOrientationClient = new DeviceOrientationClientMock; - else - pageClients.deviceOrientationClient = new DeviceOrientationClientQt; - - pageClients.deviceMotionClient = new DeviceMotionClientQt; -#endif #if ENABLE(CLIENT_BASED_GEOLOCATION) if (useMock) pageClients.geolocationClient = new GeolocationClientMock; else pageClients.geolocationClient = new GeolocationClientQt(q); #endif + page = new Page(pageClients); +#if ENABLE(DEVICE_ORIENTATION) + if (useMock) + WebCore::provideDeviceOrientationTo(page, new DeviceOrientationClientMock); + else + WebCore::provideDeviceOrientationTo(page, new DeviceOrientationClientQt); + WebCore::provideDeviceMotionTo(page, new DeviceMotionClientQt); +#endif #if ENABLE(NOTIFICATIONS) - pageClients.notificationClient = NotificationPresenterClientQt::notificationPresenter(); + WebCore::provideNotification(page, NotificationPresenterClientQt::notificationPresenter()); #endif - page = new Page(pageClients); // By default each page is put into their own unique page group, which affects popup windows // and visited links. Page groups (per process only) is a feature making it possible to use @@ -677,7 +680,7 @@ void QWebPagePrivate::mouseMoveEvent(T* ev) if (!frame->view()) return; - bool accepted = frame->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0)); + bool accepted = frame->eventHandler()->mouseMoved(convertMouseEvent(ev, 0)); ev->setAccepted(accepted); } @@ -702,7 +705,7 @@ void QWebPagePrivate::mousePressEvent(T* ev) bool accepted = false; adjustPointForClicking(ev); - PlatformMouseEvent mev(ev, 1); + PlatformMouseEvent mev = convertMouseEvent(ev, 1); // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton if (mev.button() != NoButton) accepted = frame->eventHandler()->handleMousePressEvent(mev); @@ -725,7 +728,7 @@ void QWebPagePrivate::mouseDoubleClickEvent(T *ev) return; bool accepted = false; - PlatformMouseEvent mev(ev, 2); + PlatformMouseEvent mev = convertMouseEvent(ev, 2); // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton if (mev.button() != NoButton) accepted = frame->eventHandler()->handleMousePressEvent(mev); @@ -743,7 +746,7 @@ void QWebPagePrivate::mouseTripleClickEvent(T *ev) return; bool accepted = false; - PlatformMouseEvent mev(ev, 3); + PlatformMouseEvent mev = convertMouseEvent(ev, 3); // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton if (mev.button() != NoButton) accepted = frame->eventHandler()->handleMousePressEvent(mev); @@ -782,7 +785,7 @@ void QWebPagePrivate::mouseReleaseEvent(T *ev) bool accepted = false; adjustPointForClicking(ev); - PlatformMouseEvent mev(ev, 0); + PlatformMouseEvent mev = convertMouseEvent(ev, 0); // ignore the event if we can't map Qt's mouse buttons to WebCore::MouseButton if (mev.button() != NoButton) accepted = frame->eventHandler()->handleMouseReleaseEvent(mev); @@ -852,7 +855,7 @@ void QWebPagePrivate::wheelEvent(T *ev) if (!frame->view()) return; - WebCore::PlatformWheelEvent pev(ev); + PlatformWheelEvent pev = convertWheelEvent(ev); bool accepted = frame->eventHandler()->handleWheelEvent(pev); ev->setAccepted(accepted); } @@ -1199,43 +1202,6 @@ void QWebPagePrivate::dynamicPropertyChangeEvent(QDynamicPropertyChangeEvent* ev } } } -#if USE(TILED_BACKING_STORE) - else if (event->propertyName() == "_q_TiledBackingStoreTileSize") { - WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); - if (!frame->tiledBackingStore()) - return; - QSize tileSize = q->property("_q_TiledBackingStoreTileSize").toSize(); - frame->tiledBackingStore()->setTileSize(tileSize); - } else if (event->propertyName() == "_q_TiledBackingStoreTileCreationDelay") { - WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); - if (!frame->tiledBackingStore()) - return; - int tileCreationDelay = q->property("_q_TiledBackingStoreTileCreationDelay").toInt(); - frame->tiledBackingStore()->setTileCreationDelay(static_cast<double>(tileCreationDelay) / 1000.); - } else if (event->propertyName() == "_q_TiledBackingStoreKeepAreaMultiplier") { - WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); - if (!frame->tiledBackingStore()) - return; - float keepMultiplier; - float coverMultiplier; - frame->tiledBackingStore()->getKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier); - QSizeF qSize = q->property("_q_TiledBackingStoreKeepAreaMultiplier").toSizeF(); - // setKeepAndCoverAreaMultipliers do not use FloatSize anymore, keep only the height part. - keepMultiplier = qSize.height(); - frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier); - } else if (event->propertyName() == "_q_TiledBackingStoreCoverAreaMultiplier") { - WebCore::Frame* frame = QWebFramePrivate::core(q->mainFrame()); - if (!frame->tiledBackingStore()) - return; - float keepMultiplier; - float coverMultiplier; - frame->tiledBackingStore()->getKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier); - QSizeF qSize = q->property("_q_TiledBackingStoreCoverAreaMultiplier").toSizeF(); - // setKeepAndCoverAreaMultipliers do not use FloatSize anymore, keep only the height part. - coverMultiplier = qSize.height(); - frame->tiledBackingStore()->setKeepAndCoverAreaMultipliers(keepMultiplier, coverMultiplier); - } -#endif else if (event->propertyName() == "_q_webInspectorServerPort") { InspectorServerQt* inspectorServer = InspectorServerQt::server(); inspectorServer->listen(inspectorServerPort()); @@ -1566,7 +1532,7 @@ static bool isClickableElement(Element* element, RefPtr<NodeList> list) ExceptionCode ec = 0; return isClickable || element->webkitMatchesSelector("a,*:link,*:visited,*[role=button],button,input,select,label", ec) - || computedStyle(element)->getPropertyValue(cssPropertyID("cursor")) == "pointer"; + || CSSComputedStyleDeclaration::create(element)->getPropertyValue(cssPropertyID("cursor")) == "pointer"; } static bool isValidFrameOwner(Element* element) @@ -3150,6 +3116,9 @@ bool QWebPage::event(QEvent *ev) case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + case QEvent::TouchCancel: +#endif // Return whether the default action was cancelled in the JS event handler return d->touchEvent(static_cast<QTouchEvent*>(ev)); #ifndef QT_NO_PROPERTIES @@ -3259,6 +3228,55 @@ QWebPage::LinkDelegationPolicy QWebPage::linkDelegationPolicy() const } #ifndef QT_NO_CONTEXTMENU + +static bool handleScrollbarContextMenuEvent(Scrollbar* scrollBar, QContextMenuEvent* event) +{ + if (!QApplication::style()->styleHint(QStyle::SH_ScrollBar_ContextMenu)) + return true; + + bool horizontal = (scrollBar->orientation() == HorizontalScrollbar); + + QMenu menu; + QAction* actScrollHere = menu.addAction(QCoreApplication::translate("QWebPage", "Scroll here")); + menu.addSeparator(); + + QAction* actScrollTop = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Left edge") : QCoreApplication::translate("QWebPage", "Top")); + QAction* actScrollBottom = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Right edge") : QCoreApplication::translate("QWebPage", "Bottom")); + menu.addSeparator(); + + QAction* actPageUp = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Page left") : QCoreApplication::translate("QWebPage", "Page up")); + QAction* actPageDown = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Page right") : QCoreApplication::translate("QWebPage", "Page down")); + menu.addSeparator(); + + QAction* actScrollUp = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Scroll left") : QCoreApplication::translate("QWebPage", "Scroll up")); + QAction* actScrollDown = menu.addAction(horizontal ? QCoreApplication::translate("QWebPage", "Scroll right") : QCoreApplication::translate("QWebPage", "Scroll down")); + + QAction* actionSelected = menu.exec(event->globalPos()); + + if (actionSelected == actScrollHere) { + ScrollbarTheme* theme = scrollBar->theme(); + // Set the pressed position to the middle of the thumb so that when we + // do move, the delta will be from the current pixel position of the + // thumb to the new position + int position = theme->trackPosition(scrollBar) + theme->thumbPosition(scrollBar) + theme->thumbLength(scrollBar) / 2; + scrollBar->setPressedPos(position); + const QPoint pos = scrollBar->convertFromContainingWindow(event->pos()); + scrollBar->moveThumb(horizontal ? pos.x() : pos.y()); + } else if (actionSelected == actScrollTop) + scrollBar->scrollableArea()->scroll(horizontal ? ScrollLeft : ScrollUp, ScrollByDocument); + else if (actionSelected == actScrollBottom) + scrollBar->scrollableArea()->scroll(horizontal ? ScrollRight : ScrollDown, ScrollByDocument); + else if (actionSelected == actPageUp) + scrollBar->scrollableArea()->scroll(horizontal ? ScrollLeft : ScrollUp, ScrollByPage); + else if (actionSelected == actPageDown) + scrollBar->scrollableArea()->scroll(horizontal ? ScrollRight : ScrollDown, ScrollByPage); + else if (actionSelected == actScrollUp) + scrollBar->scrollableArea()->scroll(horizontal ? ScrollLeft : ScrollUp, ScrollByLine); + else if (actionSelected == actScrollDown) + scrollBar->scrollableArea()->scroll(horizontal ? ScrollRight : ScrollDown, ScrollByLine); + return true; +} + /*! Filters the context menu event, \a event, through handlers for scrollbars and custom event handlers in the web page. Returns true if the event was handled; @@ -3276,14 +3294,14 @@ bool QWebPage::swallowContextMenuEvent(QContextMenuEvent *event) if (!RenderThemeQt::useMobileTheme()) { if (QWebFrame* webFrame = frameAt(event->pos())) { Frame* frame = QWebFramePrivate::core(webFrame); - if (Scrollbar* scrollbar = frame->view()->scrollbarAtPoint(PlatformMouseEvent(event, 1).position())) - return scrollbar->contextMenu(PlatformMouseEvent(event, 1)); + if (Scrollbar* scrollbar = frame->view()->scrollbarAtPoint(convertMouseEvent(event, 1).position())) + return handleScrollbarContextMenuEvent(scrollbar, event); } } #endif WebCore::Frame* focusedFrame = d->page->focusController()->focusedOrMainFrame(); - focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(event, 1)); + focusedFrame->eventHandler()->sendContextMenuEvent(convertMouseEvent(event, 1)); ContextMenu *menu = d->page->contextMenuController()->contextMenu(); // If the website defines its own handler then sendContextMenuEvent takes care of // calling/showing it and the context menu pointer will be zero. This is the case diff --git a/Source/WebKit/qt/Api/qwebsettings.cpp b/Source/WebKit/qt/Api/qwebsettings.cpp index 89e982140..2885f01ee 100644 --- a/Source/WebKit/qt/Api/qwebsettings.cpp +++ b/Source/WebKit/qt/Api/qwebsettings.cpp @@ -171,6 +171,10 @@ void QWebSettingsPrivate::apply() #endif #endif + value = attributes.value(QWebSettings::CSSRegionsEnabled, + global->attributes.value(QWebSettings::CSSRegionsEnabled)); + settings->setCSSRegionsEnabled(value); + value = attributes.value(QWebSettings::HyperlinkAuditingEnabled, global->attributes.value(QWebSettings::HyperlinkAuditingEnabled)); @@ -515,6 +519,7 @@ QWebSettings::QWebSettings() d->attributes.insert(QWebSettings::LocalContentCanAccessFileUrls, true); d->attributes.insert(QWebSettings::AcceleratedCompositingEnabled, true); d->attributes.insert(QWebSettings::WebGLEnabled, false); + d->attributes.insert(QWebSettings::CSSRegionsEnabled, false); d->attributes.insert(QWebSettings::HyperlinkAuditingEnabled, false); d->attributes.insert(QWebSettings::TiledBackingStoreEnabled, false); d->attributes.insert(QWebSettings::FrameFlatteningEnabled, false); diff --git a/Source/WebKit/qt/Api/qwebsettings.h b/Source/WebKit/qt/Api/qwebsettings.h index 40f7f73f9..136ee8dc4 100644 --- a/Source/WebKit/qt/Api/qwebsettings.h +++ b/Source/WebKit/qt/Api/qwebsettings.h @@ -81,6 +81,7 @@ public: SiteSpecificQuirksEnabled, JavascriptCanCloseWindows, WebGLEnabled, + CSSRegionsEnabled, HyperlinkAuditingEnabled }; enum WebGraphic { diff --git a/Source/WebKit/qt/Api/qwebview.cpp b/Source/WebKit/qt/Api/qwebview.cpp index 4a2d186a9..937d3bdca 100644 --- a/Source/WebKit/qt/Api/qwebview.cpp +++ b/Source/WebKit/qt/Api/qwebview.cpp @@ -703,7 +703,11 @@ bool QWebView::event(QEvent *e) #endif } else if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchEnd - || e->type() == QEvent::TouchUpdate) { + || e->type() == QEvent::TouchUpdate +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + || e->type() == QEvent::TouchCancel +#endif + ) { d->page->event(e); // Always return true so that we'll receive also TouchUpdate and TouchEnd events diff --git a/Source/WebKit/qt/ChangeLog b/Source/WebKit/qt/ChangeLog index 148a27369..175b43df2 100644 --- a/Source/WebKit/qt/ChangeLog +++ b/Source/WebKit/qt/ChangeLog @@ -1,3 +1,376 @@ +2012-02-24 Holger Hans Peter Freyther <holger@moiji-mobile.com> + + [Qt] Build fix. macro "QSKIP" now only takes 1 argument on Qt5 + https://bugs.webkit.org/show_bug.cgi?id=79328 + + Reviewed by Csaba Osztrogonác. + + Introduce an alternative QSKIP that can work with both Qt4 + and Qt5 without adding #ifdef to each usage site. + + * tests/benchmarks/loading/tst_loading.cpp: + (tst_Loading::load): + * tests/benchmarks/painting/tst_painting.cpp: + (tst_Painting::paint): + * tests/qdeclarativewebview/tst_qdeclarativewebview.cpp: + (tst_QDeclarativeWebView::elementAreaAt): + * tests/qwebframe/tst_qwebframe.cpp: + (tst_QWebFrame::setHtmlWithBaseURL): + * tests/qwebpage/tst_qwebpage.cpp: + (tst_QWebPage::geolocationRequestJS): + (tst_QWebPage::loadHtml5Video): + (tst_QWebPage::screenshot): + * tests/qwebview/tst_qwebview.cpp: + (tst_QWebView::reusePage): + +2012-02-24 Shinya Kawanaka <shinyak@chromium.org> + + SpellCheckRequest needs to know the context where the spellcheck happened. + https://bugs.webkit.org/show_bug.cgi?id=79320 + + Reviewed by Hajime Morita. + + * WebCoreSupport/TextCheckerClientQt.h: + (WebCore::TextCheckerClientQt::requestCheckingOfString): + +2012-02-23 Simon Hausmann <simon.hausmann@nokia.com> + + [Qt] Add support for touch cancellation + https://bugs.webkit.org/show_bug.cgi?id=79348 + + Reviewed by Kenneth Rohde Christiansen. + + Forward incoming touch cancellation events to the WebCore + event handler. + + * Api/qgraphicswebview.cpp: + (QGraphicsWebView::sceneEvent): + * Api/qwebpage.cpp: + (QWebPage::event): + * Api/qwebview.cpp: + (QWebView::event): + +2012-02-22 Hajime Morrita <morrita@chromium.org> + + NOTIFICATIONS should be implemented as PageSupplement + https://bugs.webkit.org/show_bug.cgi?id=79052 + + Reviewed by Adam Barth. + + * Api/qwebpage.cpp: + (QWebPagePrivate::QWebPagePrivate): + +2012-02-21 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/EditorClientQt.cpp: + (WebCore::EditorClientQt::shouldApplyStyle): + * WebCoreSupport/EditorClientQt.h: + (EditorClientQt): + +2012-02-22 Mihnea Ovidenie <mihnea@adobe.com> + + [Qt] REGRESSION(r108108): It made 3 fast/repaint tests fail + https://bugs.webkit.org/show_bug.cgi?id=78960 + + Reviewed by Csaba Osztrogonác. + + * Api/qwebsettings.cpp: + (QWebSettingsPrivate::apply): + (QWebSettings::QWebSettings): + * Api/qwebsettings.h: + +2012-02-22 Simon Hausmann <simon.hausmann@nokia.com> + + [Qt] Move QMenu dependant scrollbar context menu handling out of WebCore + https://bugs.webkit.org/show_bug.cgi?id=79233 + + Reviewed by Kenneth Rohde Christiansen. + + Move scrollbar context menu handling here, it's the only place where it is + used. + + * Api/qwebpage.cpp: + (handleScrollbarContextMenuEvent): + (QWebPage::swallowContextMenuEvent): + +2012-02-22 Kenneth Rohde Christiansen <kenneth@webkit.org> + + Merge setVisibleRectTrajectoryVector and adjustVisibleRect to + the more descriptive coverWithTilesIfNeeded + https://bugs.webkit.org/show_bug.cgi?id=79230 + + Reviewed by Simon Hausmann. + + * Api/qgraphicswebview.cpp: + (QGraphicsWebView::paint): + + Use coverWithTilesIfNeeded(). + +2012-02-22 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/EditorClientQt.cpp: + (WebCore::EditorClientQt::shouldApplyStyle): + * WebCoreSupport/EditorClientQt.h: + (EditorClientQt): + +2012-02-21 Csaba Osztrogonác <ossy@webkit.org> + + [Qt] tst_QWebPage::infiniteLoopJS() timeouts with DFG JIT + https://bugs.webkit.org/show_bug.cgi?id=79040 + + Reviewed by Simon Hausmann. + + * tests/qwebpage/tst_qwebpage.cpp: + (tst_QWebPage): Disable tst_QWebPage::infiniteLoopJS() until proper fix. + +2012-02-21 Andras Becsi <andras.becsi@nokia.com> + + [Qt] Print warning when importing experimental WK2 APIs in QML + https://bugs.webkit.org/show_bug.cgi?id=78817 + + Reviewed by Simon Hausmann. + + * declarative/experimental/plugin.cpp: + +2012-02-20 Benjamin Poulain <benjamin@webkit.org> + + Get rid of the LocalizationStrategy + https://bugs.webkit.org/show_bug.cgi?id=78324 + + Reviewed by Sam Weinig. + + Move the localization code from PlatformStrategiesQt.cpp + to LocalizedStringsQt.cpp. + + Get rid of LocalizationStrategy from PlatformStrategiesQt + + * WebCoreSupport/PlatformStrategiesQt.cpp: + * WebCoreSupport/PlatformStrategiesQt.h: + (PlatformStrategiesQt): + +2012-02-16 Simon Hausmann <simon.hausmann@nokia.com> + + Unreviewed brown-paper bag build fix. + + * WebCoreSupport/WebEventConversion.cpp: + (WebCore::WebKitPlatformWheelEvent::WebKitPlatformWheelEvent): + +2012-02-16 Simon Hausmann <simon.hausmann@nokia.com> + + [Qt] Move event conversion functions from WebCore to WebKit + https://bugs.webkit.org/show_bug.cgi?id=78788 + + Reviewed by Kenneth Rohde Christiansen. + + Move QtWidgets dependent mouse event constructors out of WebCore + into WebKit, similar to the web event conversions of WebKit2. + + * Api/qwebpage.cpp: + (QWebPagePrivate::mouseMoveEvent): + (QWebPagePrivate::mousePressEvent): + (QWebPagePrivate::mouseDoubleClickEvent): + (QWebPagePrivate::mouseTripleClickEvent): + (QWebPagePrivate::mouseReleaseEvent): + (QWebPagePrivate::wheelEvent): + (QWebPage::swallowContextMenuEvent): + * WebCoreSupport/FrameLoaderClientQt.cpp: + (WebCore::FrameLoaderClientQt::postProgressFinishedNotification): + * WebCoreSupport/WebEventConversion.cpp: Added. + (WebCore): + (WebCore::mouseEventModifiersFromQtKeyboardModifiers): + (WebCore::mouseEventTypeAndMouseButtonFromQEvent): + (WebKitPlatformMouseEvent): + (WebCore::WebKitPlatformMouseEvent::WebKitPlatformMouseEvent): + (WebCore::convertMouseEvent): + (WebKitPlatformWheelEvent): + (WebCore::WebKitPlatformWheelEvent::applyDelta): + (WebCore::WebKitPlatformWheelEvent::WebKitPlatformWheelEvent): + (WebCore::convertWheelEvent): + * WebCoreSupport/WebEventConversion.h: Added. + (WebCore): + +2012-02-16 Adenilson Cavalcanti <cavalcantii@gmail.com> + + [Qt][WK2] Split QWebPermissionRequest into QWebSecurityOrigin + https://bugs.webkit.org/show_bug.cgi?id=73215 + + Reviewed by Kenneth Rohde Christiansen. + + Adding a class to access security information data + (e.g. port/scheme/etc), + while allowing it to be handled in QML side. + + * declarative/plugin.cpp: + (WebKitQmlPlugin::registerTypes): + +2012-02-15 Sadrul Habib Chowdhury <sadrul@chromium.org> + + Notify ChromeClient when touch-event handlers are installed/removed. + https://bugs.webkit.org/show_bug.cgi?id=77440 + + Reviewed by Darin Fisher and Ryosuke Niwa. + + * WebCoreSupport/ChromeClientQt.h: + (WebCore::ChromeClientQt::numTouchEventHandlersChanged): + +2012-02-15 Simon Hausmann <simon.hausmann@nokia.com> + + Unreviewed Qt 4.x build fix. + + * WebCoreSupport/PageClientQt.cpp: Fix the QT_VERSION_CHECK pre-processor foo. + +2012-02-15 Simon Hausmann <simon.hausmann@nokia.com> + + [Qt] Replace use of QGLWidget/QGLContext with QOpenGLContext and QSurface for Qt 5 + https://bugs.webkit.org/show_bug.cgi?id=78694 + + Reviewed by Noam Rosenthal. + + * WebCoreSupport/PageClientQt.cpp: + (createPlatformGraphicsContext3DFromWidget): Return the QOpenGLContext and QSurface + from the QGLWidget when compiling with Qt 5, as that's what WebCore expects. + +2012-02-15 Simon Hausmann <simon.hausmann@nokia.com> + + [Qt] Move Qt platform specific GL Context/Surface creation out of WebCore into WebKit + https://bugs.webkit.org/show_bug.cgi?id=78692 + + Reviewed by Noam Rosenthal. + + Implement GLWidget and GLContext creation from the page client interface. + + * WebCoreSupport/PageClientQt.cpp: + (createPlatformGraphicsContext3DFromWidget): + (WebCore): + (WebCore::PageClientQWidget::createPlatformGraphicsContext3D): + (WebCore::PageClientQGraphicsWidget::createPlatformGraphicsContext3D): + * WebCoreSupport/PageClientQt.h: + (PageClientQWidget): + (PageClientQGraphicsWidget): + +2012-02-14 Simon Hausmann <simon.hausmann@nokia.com> + + [Qt] Eliminate first set of QtWidgets dependencies from WebCore + https://bugs.webkit.org/show_bug.cgi?id=78611 + + Reviewed by Kenneth Rohde Christiansen. + + * Api/qwebpage.cpp: Add missing includes. + * WebCoreSupport/DumpRenderTreeSupportQt.cpp: Ditto. + * WebCoreSupport/FrameLoaderClientQt.cpp: Make it compile by casting + the QObject based PlatformWidget back to QWidget before doing QWidget + specific function calls. + * WebCoreSupport/InitWebCoreQt.cpp: + (WebCore::initializeWebCoreQt): Moved QStyle specific web-graphic initialization + here from WebCore. + * WebCoreSupport/PageClientQt.cpp: + (WebCore::PageClientQWidget::setWidgetVisible): Implement show/hiding of widgets + through delegation to QWidget. + (WebCore): + (WebCore::PageClientQGraphicsWidget::setWidgetVisible): Provide empty widget + show/hide implementation, as it doesn't seem to make sense for graphicsviews. + * WebCoreSupport/PageClientQt.h: + (PageClientQWidget): + (PageClientQGraphicsWidget): + +2012-02-15 Kenneth Rohde Christiansen <kenneth@webkit.org> + + [Qt] Be smarted with tile usages during tiling + https://bugs.webkit.org/show_bug.cgi?id=78243 + + Reviewed by Simon Hausmann. + + Remove internal API used by Symbian. + + * Api/qwebpage.cpp: + (QWebPagePrivate::dynamicPropertyChangeEvent): + +2012-02-15 No'am Rosenthal <noam.rosenthal@nokia.com> + + [Texmap] Divide TextureMapperNode.cpp to 3 files. + https://bugs.webkit.org/show_bug.cgi?id=76660 + + Rename TextureMapperNode to TextureMapperLayer. + + Reviewed by Kenneth Rohde Christiansen. + + * Api/qwebframe.cpp: + (QWebFramePrivate::renderCompositedLayers): + * Api/qwebframe.h: + (WebCore): + * Api/qwebframe_p.h: + (WebCore): + (QWebFramePrivate::QWebFramePrivate): + (QWebFramePrivate): + * WebCoreSupport/PageClientQt.cpp: + (WebCore::TextureMapperLayerClientQt::TextureMapperLayerClientQt): + (WebCore::TextureMapperLayerClientQt::setTextureMapper): + (WebCore::TextureMapperLayerClientQt::~TextureMapperLayerClientQt): + (WebCore::TextureMapperLayerClientQt::syncRootLayer): + (WebCore::TextureMapperLayerClientQt::rootLayer): + (WebCore::PageClientQWidget::setRootGraphicsLayer): + (WebCore::PageClientQWidget::syncLayers): + (WebCore::PageClientQGraphicsWidget::syncLayers): + (WebCore::PageClientQGraphicsWidget::setRootGraphicsLayer): + * WebCoreSupport/PageClientQt.h: + (TextureMapperLayerClientQt): + (PageClientQWidget): + (PageClientQGraphicsWidget): + +2012-02-11 Nikolas Zimmermann <nzimmermann@rim.com> + + Convert svg/animations to use SMIL methods for driving the timeline + https://bugs.webkit.org/show_bug.cgi?id=78422 + + Reviewed by Dirk Schulze. + + Remove SVG animation sampling functionality provided for DRT, which no longer uses it. + Instead we switched the svg/animations tests to use SVGSVGElement.setCurrentTime. + + * WebCoreSupport/DumpRenderTreeSupportQt.cpp: + * WebCoreSupport/DumpRenderTreeSupportQt.h: + +2012-02-13 Enrica Casucci <enrica@apple.com> + + Build fix. Unreviewed. + + * WebCoreSupport/PlatformStrategiesQt.cpp: + (PlatformStrategiesQt::createPasteboardStrategy): + +2012-02-13 Enrica Casucci <enrica@apple.com> + + Refactor Mac platform implementation of the Pasteboard class to use Platform Strategies. + https://bugs.webkit.org/show_bug.cgi?id=78282 + + Build fix. Unreviewed. + + * WebCoreSupport/PlatformStrategiesQt.cpp: + (WebPlatformStrategies::createPasteboardStrategy): + * WebCoreSupport/PlatformStrategiesQt.h: + (PlatformStrategiesQt): + +2012-02-12 Hajime Morrita <morrita@chromium.org> + + Page should have less intrusive way to associate API implementation objects. + https://bugs.webkit.org/show_bug.cgi?id=78085 + + Reviewed by Adam Barth. + + * Api/qwebpage.cpp: + (QWebPagePrivate::QWebPagePrivate): + * WebCoreSupport/DumpRenderTreeSupportQt.cpp: + (DumpRenderTreeSupportQt::setMockDeviceOrientation): + 2012-02-09 Simon Hausmann <simon.hausmann@nokia.com> [Qt] Fix compilation with newer Qt5 diff --git a/Source/WebKit/qt/WebCoreSupport/ChromeClientQt.h b/Source/WebKit/qt/WebCoreSupport/ChromeClientQt.h index 6a576d96d..3d45b7b51 100644 --- a/Source/WebKit/qt/WebCoreSupport/ChromeClientQt.h +++ b/Source/WebKit/qt/WebCoreSupport/ChromeClientQt.h @@ -192,6 +192,7 @@ public: virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; } virtual void numWheelEventHandlersChanged(unsigned) { } + virtual void numTouchEventHandlersChanged(unsigned) { } QWebPage* m_webPage; KURL lastHoverURL; diff --git a/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp b/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp index 90254aeca..92c98cd37 100644 --- a/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp +++ b/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.cpp @@ -78,10 +78,6 @@ #include "SecurityOrigin.h" #include "SecurityPolicy.h" #include "Settings.h" -#if ENABLE(SVG) -#include "SVGDocumentExtensions.h" -#include "SVGSMILElement.h" -#endif #include "TextIterator.h" #include "ThirdPartyCookiesQt.h" #include "WebCoreTestSupport.h" @@ -102,6 +98,9 @@ #include "MediaPlayerPrivateQt.h" #endif +#include <QAction> +#include <QMenu> + using namespace WebCore; QMap<int, QWebScriptWorld*> m_worldMap; @@ -370,31 +369,6 @@ bool DumpRenderTreeSupportQt::pauseTransitionOfProperty(QWebFrame *frame, const return controller->pauseTransitionAtTime(coreNode->renderer(), propertyName, time); } -// Pause a given SVG animation on the target node at a specific time. -// This method is only intended to be used for testing the SVG animation system. -bool DumpRenderTreeSupportQt::pauseSVGAnimation(QWebFrame *frame, const QString &animationId, double time, const QString &elementId) -{ -#if !ENABLE(SVG) - return false; -#else - Frame* coreFrame = QWebFramePrivate::core(frame); - if (!coreFrame) - return false; - - Document* doc = coreFrame->document(); - Q_ASSERT(doc); - - if (!doc->svgExtensions()) - return false; - - Node* coreNode = doc->getElementById(animationId); - if (!coreNode || !SVGSMILElement::isSMILElement(coreNode)) - return false; - - return doc->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreNode), time); -#endif -} - // Returns the total number of currently running animations (includes both CSS transitions and CSS animations). int DumpRenderTreeSupportQt::numberOfActiveAnimations(QWebFrame *frame) { @@ -635,7 +609,7 @@ QVariantMap DumpRenderTreeSupportQt::computedStyleIncludingVisitedInfo(const QWe if (!webElement) return res; - RefPtr<WebCore::CSSComputedStyleDeclaration> computedStyleDeclaration = computedStyle(webElement, true); + RefPtr<WebCore::CSSComputedStyleDeclaration> computedStyleDeclaration = CSSComputedStyleDeclaration::create(webElement, true); CSSStyleDeclaration* style = static_cast<WebCore::CSSStyleDeclaration*>(computedStyleDeclaration.get()); for (unsigned i = 0; i < style->length(); i++) { QString name = style->item(i); @@ -857,7 +831,7 @@ void DumpRenderTreeSupportQt::setMockDeviceOrientation(QWebPage* page, bool canP { #if ENABLE(DEVICE_ORIENTATION) Page* corePage = QWebPagePrivate::core(page); - DeviceOrientationClientMock* mockClient = toDeviceOrientationClientMock(corePage->deviceOrientationController()->client()); + DeviceOrientationClientMock* mockClient = toDeviceOrientationClientMock(DeviceOrientationController::from(corePage)->client()); mockClient->setOrientation(DeviceOrientation::create(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma)); #endif } diff --git a/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h b/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h index 7aa9f1dce..4b0314350 100644 --- a/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h +++ b/Source/WebKit/qt/WebCoreSupport/DumpRenderTreeSupportQt.h @@ -112,7 +112,6 @@ public: static bool pauseAnimation(QWebFrame*, const QString& name, double time, const QString& elementId); static bool pauseTransitionOfProperty(QWebFrame*, const QString& name, double time, const QString& elementId); - static bool pauseSVGAnimation(QWebFrame*, const QString& animationId, double time, const QString& elementId); static void suspendActiveDOMObjects(QWebFrame* frame); static void resumeActiveDOMObjects(QWebFrame* frame); diff --git a/Source/WebKit/qt/WebCoreSupport/EditorClientQt.cpp b/Source/WebKit/qt/WebCoreSupport/EditorClientQt.cpp index 1d808031f..166e0063f 100644 --- a/Source/WebKit/qt/WebCoreSupport/EditorClientQt.cpp +++ b/Source/WebKit/qt/WebCoreSupport/EditorClientQt.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "EditorClientQt.h" -#include "CSSStyleDeclaration.h" #include "Document.h" #include "UndoStepQt.h" #include "Editor.h" @@ -48,6 +47,7 @@ #include "Range.h" #include "Settings.h" #include "SpatialNavigation.h" +#include "StylePropertySet.h" #include "WindowsKeyboardCodes.h" #include "qwebpage.h" #include "qwebpage_p.h" @@ -170,12 +170,12 @@ bool EditorClientQt::shouldChangeSelectedRange(Range* currentRange, Range* propo return acceptsEditing; } -bool EditorClientQt::shouldApplyStyle(WebCore::CSSStyleDeclaration* style, +bool EditorClientQt::shouldApplyStyle(WebCore::StylePropertySet* style, WebCore::Range* range) { if (dumpEditingCallbacks) printf("EDITING DELEGATE: shouldApplyStyle:%s toElementsInDOMRange:%s\n", - QString(style->cssText()).toUtf8().constData(), dumpRange(range).toUtf8().constData()); + QString(style->asText()).toUtf8().constData(), dumpRange(range).toUtf8().constData()); return acceptsEditing; } diff --git a/Source/WebKit/qt/WebCoreSupport/EditorClientQt.h b/Source/WebKit/qt/WebCoreSupport/EditorClientQt.h index c20f97576..2830989e4 100644 --- a/Source/WebKit/qt/WebCoreSupport/EditorClientQt.h +++ b/Source/WebKit/qt/WebCoreSupport/EditorClientQt.h @@ -63,7 +63,7 @@ public: virtual bool shouldInsertText(const String&, Range*, EditorInsertAction); virtual bool shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity, bool stillSelecting); - virtual bool shouldApplyStyle(CSSStyleDeclaration*, Range*); + virtual bool shouldApplyStyle(StylePropertySet*, Range*); virtual bool shouldMoveRangeAfterDelete(Range*, Range*); diff --git a/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp b/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp index b3588361e..8364219d6 100644 --- a/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp +++ b/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp @@ -73,6 +73,7 @@ #include "V8DOMWindow.h" #endif #include "ViewportArguments.h" +#include "WebEventConversion.h" #include "qwebframe.h" #include "qwebframe_p.h" @@ -606,7 +607,7 @@ void FrameLoaderClientQt::postProgressFinishedNotification() QPoint localPos = view->mapFromGlobal(QCursor::pos()); if (view->rect().contains(localPos)) { QMouseEvent event(QEvent::MouseMove, localPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); - m_frame->eventHandler()->mouseMoved(PlatformMouseEvent(&event, 0)); + m_frame->eventHandler()->mouseMoved(convertMouseEvent(&event, 0)); } } } @@ -1451,15 +1452,16 @@ public: virtual void invalidateRect(const IntRect& r) { if (platformWidget()) - platformWidget()->update(r); + static_cast<QWidget*>(platformWidget())->update(r); } virtual void frameRectsChanged() { - if (!platformWidget()) + QWidget* widget = static_cast<QWidget*>(platformWidget()); + if (!widget) return; IntRect windowRect = convertToContainingWindow(IntRect(0, 0, frameRect().width(), frameRect().height())); - platformWidget()->setGeometry(windowRect); + widget->setGeometry(windowRect); ScrollView* parentScrollView = parent(); if (!parentScrollView) @@ -1468,14 +1470,14 @@ public: ASSERT(parentScrollView->isFrameView()); IntRect clipRect(static_cast<FrameView*>(parentScrollView)->windowClipRect()); clipRect.move(-windowRect.x(), -windowRect.y()); - clipRect.intersect(platformWidget()->rect()); + clipRect.intersect(widget->rect()); QRegion clipRegion = QRegion(clipRect); - platformWidget()->setMask(clipRegion); + widget->setMask(clipRegion); handleVisibility(); - platformWidget()->update(); + widget->update(); } virtual void show() @@ -1490,10 +1492,11 @@ private: if (!isVisible()) return; + QWidget* widget = static_cast<QWidget*>(platformWidget()); // If setMask is set with an empty QRegion, no clipping will // be performed, so in that case we hide the platformWidget. - QRegion mask = platformWidget()->mask(); - platformWidget()->setVisible(!mask.isEmpty()); + QRegion mask = widget->mask(); + widget->setVisible(!mask.isEmpty()); } }; @@ -1590,7 +1593,7 @@ PassRefPtr<Widget> FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, styleSheet += QString::fromLatin1(getPropertyName(property)); styleSheet += QLatin1Char(':'); - styleSheet += computedStyle(element)->getPropertyValue(property); + styleSheet += CSSComputedStyleDeclaration::create(element)->getPropertyValue(property); styleSheet += QLatin1Char(';'); } diff --git a/Source/WebKit/qt/WebCoreSupport/InitWebCoreQt.cpp b/Source/WebKit/qt/WebCoreSupport/InitWebCoreQt.cpp index 40f6fe7c9..5cbd82c58 100644 --- a/Source/WebKit/qt/WebCoreSupport/InitWebCoreQt.cpp +++ b/Source/WebKit/qt/WebCoreSupport/InitWebCoreQt.cpp @@ -30,6 +30,7 @@ #include "config.h" #include "InitWebCoreQt.h" +#include "Image.h" #include "NotImplemented.h" #include "PlatformStrategiesQt.h" #include "ScriptController.h" @@ -39,6 +40,8 @@ #endif #include "qwebelement_p.h" +#include <QApplication> +#include <QStyle> #include <runtime/InitializeThreading.h> #include <wtf/MainThread.h> @@ -63,6 +66,11 @@ void initializeWebCoreQt() InitWebCoreSystemInterface(); #endif + // QWebSettings::SearchCancelButtonGraphic + Image::setPlatformResource("searchCancelButton", QApplication::style()->standardPixmap(QStyle::SP_DialogCloseButton)); + // QWebSettings::SearchCancelButtonPressedGraphic + Image::setPlatformResource("searchCancelButtonPressed", QApplication::style()->standardPixmap(QStyle::SP_DialogCloseButton)); + initialized = true; } diff --git a/Source/WebKit/qt/WebCoreSupport/PageClientQt.cpp b/Source/WebKit/qt/WebCoreSupport/PageClientQt.cpp index 45dcfbbe1..6f96ce1ba 100644 --- a/Source/WebKit/qt/WebCoreSupport/PageClientQt.cpp +++ b/Source/WebKit/qt/WebCoreSupport/PageClientQt.cpp @@ -27,56 +27,93 @@ #include <QX11Info> #endif +#if ENABLE(WEBGL) +#include <QGLWidget> + +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +#include <QWindow> +#endif + +static void createPlatformGraphicsContext3DFromWidget(QWidget* widget, PlatformGraphicsContext3D* context, + PlatformGraphicsSurface3D* surface) +{ + *context = 0; + *surface = 0; + QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>(widget); + if (!scrollArea) + return; + + QGLWidget* glViewport = qobject_cast<QGLWidget*>(scrollArea->viewport()); + if (!glViewport) + return; + QGLWidget* glWidget = new QGLWidget(0, glViewport); + if (glWidget->isValid()) { + // Geometry can be set to zero because m_glWidget is used only for its QGLContext. + glWidget->setGeometry(0, 0, 0, 0); +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + *surface = glWidget->windowHandle(); + *context = glWidget->context()->contextHandle(); +#else + *surface = glWidget; + *context = const_cast<QGLContext*>(glWidget->context()); +#endif + } else { + delete glWidget; + glWidget = 0; + } +} +#endif + #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) #include "TextureMapper.h" -#include "texmap/TextureMapperNode.h" +#include "texmap/TextureMapperLayer.h" #endif namespace WebCore { #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) -TextureMapperNodeClientQt::TextureMapperNodeClientQt(QWebFrame* frame, GraphicsLayer* layer) +TextureMapperLayerClientQt::TextureMapperLayerClientQt(QWebFrame* frame, GraphicsLayer* layer) : m_frame(frame) , m_rootGraphicsLayer(GraphicsLayer::create(0)) { - m_frame->d->rootTextureMapperNode = rootNode(); + m_frame->d->rootTextureMapperLayer = rootLayer(); m_rootGraphicsLayer->addChild(layer); m_rootGraphicsLayer->setDrawsContent(false); m_rootGraphicsLayer->setMasksToBounds(false); m_rootGraphicsLayer->setSize(IntSize(1, 1)); } -void TextureMapperNodeClientQt::setTextureMapper(const PassOwnPtr<TextureMapper>& textureMapper) +void TextureMapperLayerClientQt::setTextureMapper(const PassOwnPtr<TextureMapper>& textureMapper) { m_frame->d->textureMapper = textureMapper; - m_frame->d->rootTextureMapperNode->setTextureMapper(m_frame->d->textureMapper.get()); + m_frame->d->rootTextureMapperLayer->setTextureMapper(m_frame->d->textureMapper.get()); } -TextureMapperNodeClientQt::~TextureMapperNodeClientQt() +TextureMapperLayerClientQt::~TextureMapperLayerClientQt() { - m_frame->d->rootTextureMapperNode = 0; + m_frame->d->rootTextureMapperLayer = 0; } -void TextureMapperNodeClientQt::syncRootLayer() +void TextureMapperLayerClientQt::syncRootLayer() { m_rootGraphicsLayer->syncCompositingStateForThisLayerOnly(); } -TextureMapperNode* TextureMapperNodeClientQt::rootNode() +TextureMapperLayer* TextureMapperLayerClientQt::rootLayer() { - return toTextureMapperNode(m_rootGraphicsLayer.get()); + return toTextureMapperLayer(m_rootGraphicsLayer.get()); } void PageClientQWidget::setRootGraphicsLayer(GraphicsLayer* layer) { if (layer) { - textureMapperNodeClient = adoptPtr(new TextureMapperNodeClientQt(page->mainFrame(), layer)); - textureMapperNodeClient->setTextureMapper(TextureMapper::create()); - textureMapperNodeClient->syncRootLayer(); + TextureMapperLayerClient = adoptPtr(new TextureMapperLayerClientQt(page->mainFrame(), layer)); + TextureMapperLayerClient->setTextureMapper(TextureMapper::create()); + TextureMapperLayerClient->syncRootLayer(); return; } - textureMapperNodeClient.clear(); + TextureMapperLayerClient.clear(); } void PageClientQWidget::markForSync(bool scheduleSync) @@ -88,12 +125,12 @@ void PageClientQWidget::markForSync(bool scheduleSync) void PageClientQWidget::syncLayers(Timer<PageClientQWidget>*) { - if (textureMapperNodeClient) - textureMapperNodeClient->syncRootLayer(); + if (TextureMapperLayerClient) + TextureMapperLayerClient->syncRootLayer(); QWebFramePrivate::core(page->mainFrame())->view()->syncCompositingStateIncludingSubframes(); - if (!textureMapperNodeClient) + if (!TextureMapperLayerClient) return; - if (textureMapperNodeClient->rootNode()->descendantsOrSelfHaveRunningAnimations() && !syncTimer.isActive()) + if (TextureMapperLayerClient->rootLayer()->descendantsOrSelfHaveRunningAnimations() && !syncTimer.isActive()) syncTimer.startOneShot(1.0 / 60.0); update(view->rect()); } @@ -178,6 +215,22 @@ QRectF PageClientQWidget::windowRect() const return QRectF(view->window()->geometry()); } +void PageClientQWidget::setWidgetVisible(Widget* widget, bool visible) +{ + QWidget* qtWidget = qobject_cast<QWidget*>(widget->platformWidget()); + if (!qtWidget) + return; + qtWidget->setVisible(visible); +} + +#if ENABLE(WEBGL) +void PageClientQWidget::createPlatformGraphicsContext3D(PlatformGraphicsContext3D* context, + PlatformGraphicsSurface3D* surface) +{ + createPlatformGraphicsContext3DFromWidget(view, context, surface); +} +#endif + #if !defined(QT_NO_GRAPHICSVIEW) PageClientQGraphicsWidget::~PageClientQGraphicsWidget() { @@ -239,17 +292,17 @@ void PageClientQGraphicsWidget::createOrDeleteOverlay() void PageClientQGraphicsWidget::syncLayers() { #if USE(TEXTURE_MAPPER) - if (textureMapperNodeClient) - textureMapperNodeClient->syncRootLayer(); + if (TextureMapperLayerClient) + TextureMapperLayerClient->syncRootLayer(); #endif QWebFramePrivate::core(page->mainFrame())->view()->syncCompositingStateIncludingSubframes(); #if USE(TEXTURE_MAPPER) - if (!textureMapperNodeClient) + if (!TextureMapperLayerClient) return; - if (textureMapperNodeClient->rootNode()->descendantsOrSelfHaveRunningAnimations() && !syncTimer.isActive()) + if (TextureMapperLayerClient->rootLayer()->descendantsOrSelfHaveRunningAnimations() && !syncTimer.isActive()) syncTimer.startOneShot(1.0 / 60.0); update(view->boundingRect().toAlignedRect()); #endif @@ -259,18 +312,18 @@ void PageClientQGraphicsWidget::syncLayers() void PageClientQGraphicsWidget::setRootGraphicsLayer(GraphicsLayer* layer) { if (layer) { - textureMapperNodeClient = adoptPtr(new TextureMapperNodeClientQt(page->mainFrame(), layer)); + TextureMapperLayerClient = adoptPtr(new TextureMapperLayerClientQt(page->mainFrame(), layer)); #if USE(TEXTURE_MAPPER_GL) QGraphicsView* graphicsView = view->scene()->views()[0]; if (graphicsView && graphicsView->viewport() && graphicsView->viewport()->inherits("QGLWidget")) { - textureMapperNodeClient->setTextureMapper(TextureMapper::create(TextureMapper::OpenGLMode)); + TextureMapperLayerClient->setTextureMapper(TextureMapper::create(TextureMapper::OpenGLMode)); return; } #endif - textureMapperNodeClient->setTextureMapper(TextureMapper::create()); + TextureMapperLayerClient->setTextureMapper(TextureMapper::create()); return; } - textureMapperNodeClient.clear(); + TextureMapperLayerClient.clear(); } #else void PageClientQGraphicsWidget::setRootGraphicsLayer(GraphicsLayer* layer) @@ -405,6 +458,11 @@ QStyle* PageClientQGraphicsWidget::style() const return view->style(); } +void PageClientQGraphicsWidget::setWidgetVisible(Widget*, bool) +{ + // Doesn't make sense, does it? +} + QRectF PageClientQGraphicsWidget::windowRect() const { if (!view->scene()) @@ -415,4 +473,12 @@ QRectF PageClientQGraphicsWidget::windowRect() const } #endif // QT_NO_GRAPHICSVIEW +#if ENABLE(WEBGL) +void PageClientQGraphicsWidget::createPlatformGraphicsContext3D(PlatformGraphicsContext3D* context, + PlatformGraphicsSurface3D* surface) +{ + createPlatformGraphicsContext3DFromWidget(ownerWidget(), context, surface); +} +#endif + } // namespace WebCore diff --git a/Source/WebKit/qt/WebCoreSupport/PageClientQt.h b/Source/WebKit/qt/WebCoreSupport/PageClientQt.h index 3480449d2..9a2636572 100644 --- a/Source/WebKit/qt/WebCoreSupport/PageClientQt.h +++ b/Source/WebKit/qt/WebCoreSupport/PageClientQt.h @@ -44,13 +44,13 @@ namespace WebCore { #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) -class TextureMapperNodeClientQt { +class TextureMapperLayerClientQt { public: - TextureMapperNodeClientQt(QWebFrame*, GraphicsLayer*); - virtual ~TextureMapperNodeClientQt(); + TextureMapperLayerClientQt(QWebFrame*, GraphicsLayer*); + virtual ~TextureMapperLayerClientQt(); void setTextureMapper(const PassOwnPtr<TextureMapper>&); void syncRootLayer(); - TextureMapperNode* rootNode(); + TextureMapperLayer* rootLayer(); private: QWebFrame* m_frame; @@ -97,6 +97,13 @@ public: virtual QRectF windowRect() const; + virtual void setWidgetVisible(Widget*, bool visible); + +#if ENABLE(WEBGL) + virtual void createPlatformGraphicsContext3D(PlatformGraphicsContext3D*, + PlatformGraphicsSurface3D*); +#endif + QWidget* view; QWebPage* page; @@ -114,7 +121,7 @@ public: #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) Timer<PageClientQWidget> syncTimer; - OwnPtr<TextureMapperNodeClientQt> textureMapperNodeClient; + OwnPtr<TextureMapperLayerClientQt> TextureMapperLayerClient; #endif }; @@ -198,6 +205,13 @@ public: virtual bool viewResizesToContentsEnabled() const { return viewResizesToContents; } + virtual void setWidgetVisible(Widget*, bool); + +#if ENABLE(WEBGL) + virtual void createPlatformGraphicsContext3D(PlatformGraphicsContext3D*, + PlatformGraphicsSurface3D*); +#endif + void createOrDeleteOverlay(); #if USE(TILED_BACKING_STORE) @@ -223,7 +237,7 @@ public: #if USE(ACCELERATED_COMPOSITING) #if USE(TEXTURE_MAPPER) - OwnPtr<TextureMapperNodeClientQt> textureMapperNodeClient; + OwnPtr<TextureMapperLayerClientQt> TextureMapperLayerClient; #else QWeakPointer<QGraphicsObject> rootGraphicsLayer; #endif diff --git a/Source/WebKit/qt/WebCoreSupport/PlatformStrategiesQt.cpp b/Source/WebKit/qt/WebCoreSupport/PlatformStrategiesQt.cpp index 64d424d95..cd4ab0d72 100644 --- a/Source/WebKit/qt/WebCoreSupport/PlatformStrategiesQt.cpp +++ b/Source/WebKit/qt/WebCoreSupport/PlatformStrategiesQt.cpp @@ -68,14 +68,14 @@ PluginStrategy* PlatformStrategiesQt::createPluginStrategy() return this; } -LocalizationStrategy* PlatformStrategiesQt::createLocalizationStrategy() +VisitedLinkStrategy* PlatformStrategiesQt::createVisitedLinkStrategy() { return this; } -VisitedLinkStrategy* PlatformStrategiesQt::createVisitedLinkStrategy() +PasteboardStrategy* PlatformStrategiesQt::createPasteboardStrategy() { - return this; + return 0; } void PlatformStrategiesQt::notifyCookiesChanged() @@ -145,608 +145,6 @@ void PlatformStrategiesQt::getPluginInfo(const WebCore::Page* page, Vector<WebCo } - -// LocalizationStrategy - -String PlatformStrategiesQt::inputElementAltText() -{ - return QCoreApplication::translate("QWebPage", "Submit", "Submit (input element) alt text for <input> elements with no alt, title, or value"); -} - -String PlatformStrategiesQt::resetButtonDefaultLabel() -{ - return QCoreApplication::translate("QWebPage", "Reset", "default label for Reset buttons in forms on web pages"); -} - -String PlatformStrategiesQt::searchableIndexIntroduction() -{ - return QCoreApplication::translate("QWebPage", "This is a searchable index. Enter search keywords: ", "text that appears at the start of nearly-obsolete web pages in the form of a 'searchable index'"); -} - -String PlatformStrategiesQt::submitButtonDefaultLabel() -{ - return QCoreApplication::translate("QWebPage", "Submit", "default label for Submit buttons in forms on web pages"); -} - -String PlatformStrategiesQt::fileButtonChooseFileLabel() -{ - return QCoreApplication::translate("QWebPage", "Choose File", "title for a single file chooser button used in HTML forms"); -} - -String PlatformStrategiesQt::fileButtonChooseMultipleFilesLabel() -{ - return QCoreApplication::translate("QWebPage", "Choose Files", "title for a multiple file chooser button used in HTML forms. This title should be as short as possible."); -} - -String PlatformStrategiesQt::fileButtonNoFileSelectedLabel() -{ - return QCoreApplication::translate("QWebPage", "No file selected", "text to display in file button used in HTML forms when no file is selected"); -} - -String PlatformStrategiesQt::fileButtonNoFilesSelectedLabel() -{ - return QCoreApplication::translate("QWebPage", "No files selected", "text to display in file button used in HTML forms when no files are selected and the button allows multiple files to be selected"); -} - -String PlatformStrategiesQt::defaultDetailsSummaryText() -{ - return QCoreApplication::translate("QWebPage", "Details", "text to display in <details> tag when it has no <summary> child"); -} - -String PlatformStrategiesQt::contextMenuItemTagOpenLinkInNewWindow() -{ - return QCoreApplication::translate("QWebPage", "Open in New Window", "Open in New Window context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagDownloadLinkToDisk() -{ - return QCoreApplication::translate("QWebPage", "Save Link...", "Download Linked File context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagCopyLinkToClipboard() -{ - return QCoreApplication::translate("QWebPage", "Copy Link", "Copy Link context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagOpenImageInNewWindow() -{ - return QCoreApplication::translate("QWebPage", "Open Image", "Open Image in New Window context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagDownloadImageToDisk() -{ - return QCoreApplication::translate("QWebPage", "Save Image", "Download Image context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagCopyImageToClipboard() -{ - return QCoreApplication::translate("QWebPage", "Copy Image", "Copy Link context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagCopyImageUrlToClipboard() -{ - return QCoreApplication::translate("QWebPage", "Copy Image Address", "Copy Image Address menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagOpenVideoInNewWindow() -{ - return QCoreApplication::translate("QWebPage", "Open Video", "Open Video in New Window"); -} - -String PlatformStrategiesQt::contextMenuItemTagOpenAudioInNewWindow() -{ - return QCoreApplication::translate("QWebPage", "Open Audio", "Open Audio in New Window"); -} - -String PlatformStrategiesQt::contextMenuItemTagCopyVideoLinkToClipboard() -{ - return QCoreApplication::translate("QWebPage", "Copy Video", "Copy Video Link Location"); -} - -String PlatformStrategiesQt::contextMenuItemTagCopyAudioLinkToClipboard() -{ - return QCoreApplication::translate("QWebPage", "Copy Audio", "Copy Audio Link Location"); -} - -String PlatformStrategiesQt::contextMenuItemTagToggleMediaControls() -{ - return QCoreApplication::translate("QWebPage", "Toggle Controls", "Toggle Media Controls"); -} - -String PlatformStrategiesQt::contextMenuItemTagToggleMediaLoop() -{ - return QCoreApplication::translate("QWebPage", "Toggle Loop", "Toggle Media Loop Playback"); -} - -String PlatformStrategiesQt::contextMenuItemTagEnterVideoFullscreen() -{ - return QCoreApplication::translate("QWebPage", "Enter Fullscreen", "Switch Video to Fullscreen"); -} - -String PlatformStrategiesQt::contextMenuItemTagMediaPlay() -{ - return QCoreApplication::translate("QWebPage", "Play", "Play"); -} - -String PlatformStrategiesQt::contextMenuItemTagMediaPause() -{ - return QCoreApplication::translate("QWebPage", "Pause", "Pause"); -} - -String PlatformStrategiesQt::contextMenuItemTagMediaMute() -{ - return QCoreApplication::translate("QWebPage", "Mute", "Mute"); -} - -String PlatformStrategiesQt::contextMenuItemTagOpenFrameInNewWindow() -{ - return QCoreApplication::translate("QWebPage", "Open Frame", "Open Frame in New Window context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagCopy() -{ - return QCoreApplication::translate("QWebPage", "Copy", "Copy context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagGoBack() -{ - return QCoreApplication::translate("QWebPage", "Go Back", "Back context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagGoForward() -{ - return QCoreApplication::translate("QWebPage", "Go Forward", "Forward context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagStop() -{ - return QCoreApplication::translate("QWebPage", "Stop", "Stop context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagReload() -{ - return QCoreApplication::translate("QWebPage", "Reload", "Reload context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagCut() -{ - return QCoreApplication::translate("QWebPage", "Cut", "Cut context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagPaste() -{ - return QCoreApplication::translate("QWebPage", "Paste", "Paste context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagSelectAll() -{ - return QCoreApplication::translate("QWebPage", "Select All", "Select All context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagNoGuessesFound() -{ - return QCoreApplication::translate("QWebPage", "No Guesses Found", "No Guesses Found context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagIgnoreSpelling() -{ - return QCoreApplication::translate("QWebPage", "Ignore", "Ignore Spelling context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagLearnSpelling() -{ - return QCoreApplication::translate("QWebPage", "Add To Dictionary", "Learn Spelling context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagSearchWeb() -{ - return QCoreApplication::translate("QWebPage", "Search The Web", "Search The Web context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagLookUpInDictionary(const String&) -{ - return QCoreApplication::translate("QWebPage", "Look Up In Dictionary", "Look Up in Dictionary context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagOpenLink() -{ - return QCoreApplication::translate("QWebPage", "Open Link", "Open Link context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagIgnoreGrammar() -{ - return QCoreApplication::translate("QWebPage", "Ignore", "Ignore Grammar context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagSpellingMenu() -{ - return QCoreApplication::translate("QWebPage", "Spelling", "Spelling and Grammar context sub-menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagShowSpellingPanel(bool show) -{ - return show ? QCoreApplication::translate("QWebPage", "Show Spelling and Grammar", "menu item title") : - QCoreApplication::translate("QWebPage", "Hide Spelling and Grammar", "menu item title"); -} - -String PlatformStrategiesQt::contextMenuItemTagCheckSpelling() -{ - return QCoreApplication::translate("QWebPage", "Check Spelling", "Check spelling context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagCheckSpellingWhileTyping() -{ - return QCoreApplication::translate("QWebPage", "Check Spelling While Typing", "Check spelling while typing context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagCheckGrammarWithSpelling() -{ - return QCoreApplication::translate("QWebPage", "Check Grammar With Spelling", "Check grammar with spelling context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagFontMenu() -{ - return QCoreApplication::translate("QWebPage", "Fonts", "Font context sub-menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagBold() -{ - return QCoreApplication::translate("QWebPage", "Bold", "Bold context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagItalic() -{ - return QCoreApplication::translate("QWebPage", "Italic", "Italic context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagUnderline() -{ - return QCoreApplication::translate("QWebPage", "Underline", "Underline context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagOutline() -{ - return QCoreApplication::translate("QWebPage", "Outline", "Outline context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagWritingDirectionMenu() -{ - return QCoreApplication::translate("QWebPage", "Direction", "Writing direction context sub-menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagTextDirectionMenu() -{ - return QCoreApplication::translate("QWebPage", "Text Direction", "Text direction context sub-menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagDefaultDirection() -{ - return QCoreApplication::translate("QWebPage", "Default", "Default writing direction context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagLeftToRight() -{ - return QCoreApplication::translate("QWebPage", "Left to Right", "Left to Right context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagRightToLeft() -{ - return QCoreApplication::translate("QWebPage", "Right to Left", "Right to Left context menu item"); -} - -String PlatformStrategiesQt::contextMenuItemTagInspectElement() -{ - return QCoreApplication::translate("QWebPage", "Inspect", "Inspect Element context menu item"); -} - -String PlatformStrategiesQt::searchMenuNoRecentSearchesText() -{ - return QCoreApplication::translate("QWebPage", "No recent searches", "Label for only item in menu that appears when clicking on the search field image, when no searches have been performed"); -} - -String PlatformStrategiesQt::searchMenuRecentSearchesText() -{ - return QCoreApplication::translate("QWebPage", "Recent searches", "label for first item in the menu that appears when clicking on the search field image, used as embedded menu title"); -} - -String PlatformStrategiesQt::searchMenuClearRecentSearchesText() -{ - return QCoreApplication::translate("QWebPage", "Clear recent searches", "menu item in Recent Searches menu that empties menu's contents"); -} - -String PlatformStrategiesQt::AXWebAreaText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXLinkText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXListMarkerText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXImageMapText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXHeadingText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXDefinitionListTermText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXDefinitionListDefinitionText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXButtonActionVerb() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXRadioButtonActionVerb() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXTextFieldActionVerb() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXCheckedCheckBoxActionVerb() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXUncheckedCheckBoxActionVerb() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXMenuListActionVerb() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXMenuListPopupActionVerb() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::AXLinkActionVerb() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::missingPluginText() -{ - return QCoreApplication::translate("QWebPage", "Missing Plug-in", "Label text to be used when a plug-in is missing"); -} - -String PlatformStrategiesQt::crashedPluginText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::multipleFileUploadText(unsigned) -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::unknownFileSizeText() -{ - return QCoreApplication::translate("QWebPage", "Unknown", "Unknown filesize FTP directory listing item"); -} - -String PlatformStrategiesQt::imageTitle(const String& filename, const IntSize& size) -{ - return QCoreApplication::translate("QWebPage", "%1 (%2x%3 pixels)", "Title string for images").arg(filename).arg(size.width()).arg(size.height()); -} - -String PlatformStrategiesQt::mediaElementLoadingStateText() -{ - return QCoreApplication::translate("QWebPage", "Loading...", "Media controller status message when the media is loading"); -} - -String PlatformStrategiesQt::mediaElementLiveBroadcastStateText() -{ - return QCoreApplication::translate("QWebPage", "Live Broadcast", "Media controller status message when watching a live broadcast"); -} - -#if ENABLE(VIDEO) - -String PlatformStrategiesQt::localizedMediaControlElementString(const String& name) -{ - if (name == "AudioElement") - return QCoreApplication::translate("QWebPage", "Audio Element", "Media controller element"); - if (name == "VideoElement") - return QCoreApplication::translate("QWebPage", "Video Element", "Media controller element"); - if (name == "MuteButton") - return QCoreApplication::translate("QWebPage", "Mute Button", "Media controller element"); - if (name == "UnMuteButton") - return QCoreApplication::translate("QWebPage", "Unmute Button", "Media controller element"); - if (name == "PlayButton") - return QCoreApplication::translate("QWebPage", "Play Button", "Media controller element"); - if (name == "PauseButton") - return QCoreApplication::translate("QWebPage", "Pause Button", "Media controller element"); - if (name == "Slider") - return QCoreApplication::translate("QWebPage", "Slider", "Media controller element"); - if (name == "SliderThumb") - return QCoreApplication::translate("QWebPage", "Slider Thumb", "Media controller element"); - if (name == "RewindButton") - return QCoreApplication::translate("QWebPage", "Rewind Button", "Media controller element"); - if (name == "ReturnToRealtimeButton") - return QCoreApplication::translate("QWebPage", "Return to Real-time Button", "Media controller element"); - if (name == "CurrentTimeDisplay") - return QCoreApplication::translate("QWebPage", "Elapsed Time", "Media controller element"); - if (name == "TimeRemainingDisplay") - return QCoreApplication::translate("QWebPage", "Remaining Time", "Media controller element"); - if (name == "StatusDisplay") - return QCoreApplication::translate("QWebPage", "Status Display", "Media controller element"); - if (name == "FullscreenButton") - return QCoreApplication::translate("QWebPage", "Fullscreen Button", "Media controller element"); - if (name == "SeekForwardButton") - return QCoreApplication::translate("QWebPage", "Seek Forward Button", "Media controller element"); - if (name == "SeekBackButton") - return QCoreApplication::translate("QWebPage", "Seek Back Button", "Media controller element"); - - return String(); -} - -String PlatformStrategiesQt::localizedMediaControlElementHelpText(const String& name) -{ - if (name == "AudioElement") - return QCoreApplication::translate("QWebPage", "Audio element playback controls and status display", "Media controller element"); - if (name == "VideoElement") - return QCoreApplication::translate("QWebPage", "Video element playback controls and status display", "Media controller element"); - if (name == "MuteButton") - return QCoreApplication::translate("QWebPage", "Mute audio tracks", "Media controller element"); - if (name == "UnMuteButton") - return QCoreApplication::translate("QWebPage", "Unmute audio tracks", "Media controller element"); - if (name == "PlayButton") - return QCoreApplication::translate("QWebPage", "Begin playback", "Media controller element"); - if (name == "PauseButton") - return QCoreApplication::translate("QWebPage", "Pause playback", "Media controller element"); - if (name == "Slider") - return QCoreApplication::translate("QWebPage", "Movie time scrubber", "Media controller element"); - if (name == "SliderThumb") - return QCoreApplication::translate("QWebPage", "Movie time scrubber thumb", "Media controller element"); - if (name == "RewindButton") - return QCoreApplication::translate("QWebPage", "Rewind movie", "Media controller element"); - if (name == "ReturnToRealtimeButton") - return QCoreApplication::translate("QWebPage", "Return streaming movie to real-time", "Media controller element"); - if (name == "CurrentTimeDisplay") - return QCoreApplication::translate("QWebPage", "Current movie time", "Media controller element"); - if (name == "TimeRemainingDisplay") - return QCoreApplication::translate("QWebPage", "Remaining movie time", "Media controller element"); - if (name == "StatusDisplay") - return QCoreApplication::translate("QWebPage", "Current movie status", "Media controller element"); - if (name == "FullscreenButton") - return QCoreApplication::translate("QWebPage", "Play movie in full-screen mode", "Media controller element"); - if (name == "SeekForwardButton") - return QCoreApplication::translate("QWebPage", "Seek quickly back", "Media controller element"); - if (name == "SeekBackButton") - return QCoreApplication::translate("QWebPage", "Seek quickly forward", "Media controller element"); - - ASSERT_NOT_REACHED(); - return String(); -} - -String PlatformStrategiesQt::localizedMediaTimeDescription(float time) -{ - if (!isfinite(time)) - return QCoreApplication::translate("QWebPage", "Indefinite time", "Media time description"); - - int seconds = (int)fabsf(time); - int days = seconds / (60 * 60 * 24); - int hours = seconds / (60 * 60); - int minutes = (seconds / 60) % 60; - seconds %= 60; - - if (days) - return QCoreApplication::translate("QWebPage", "%1 days %2 hours %3 minutes %4 seconds", "Media time description").arg(days).arg(hours).arg(minutes).arg(seconds); - - if (hours) - return QCoreApplication::translate("QWebPage", "%1 hours %2 minutes %3 seconds", "Media time description").arg(hours).arg(minutes).arg(seconds); - - if (minutes) - return QCoreApplication::translate("QWebPage", "%1 minutes %2 seconds", "Media time description").arg(minutes).arg(seconds); - - return QCoreApplication::translate("QWebPage", "%1 seconds", "Media time description").arg(seconds); -} - -#else // ENABLE(VIDEO) -// FIXME: #if ENABLE(VIDEO) should be in the base class - -String PlatformStrategiesQt::localizedMediaControlElementString(const String& name) -{ - return String(); -} - -String PlatformStrategiesQt::localizedMediaControlElementHelpText(const String& name) -{ - return String(); -} - -String PlatformStrategiesQt::localizedMediaTimeDescription(float time) -{ - return String(); -} - -#endif // ENABLE(VIDEO) - - -String PlatformStrategiesQt::validationMessageValueMissingText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::validationMessageTypeMismatchText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::validationMessagePatternMismatchText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::validationMessageTooLongText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::validationMessageRangeUnderflowText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::validationMessageRangeOverflowText() -{ - notImplemented(); - return String(); -} - -String PlatformStrategiesQt::validationMessageStepMismatchText() -{ - notImplemented(); - return String(); -} - - // VisitedLinkStrategy bool PlatformStrategiesQt::isLinkVisited(Page* page, LinkHash hash, const KURL& baseURL, const AtomicString& attributeURL) diff --git a/Source/WebKit/qt/WebCoreSupport/PlatformStrategiesQt.h b/Source/WebKit/qt/WebCoreSupport/PlatformStrategiesQt.h index 504919e38..9dd7e79cf 100644 --- a/Source/WebKit/qt/WebCoreSupport/PlatformStrategiesQt.h +++ b/Source/WebKit/qt/WebCoreSupport/PlatformStrategiesQt.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2012 Apple Inc. All rights reserved. * Copyright (C) 2010 INdT - Instituto Nokia de Tecnologia * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * @@ -29,16 +29,16 @@ #define PlatformStrategiesQt_h #include <CookiesStrategy.h> -#include <LocalizationStrategy.h> #include <PlatformStrategies.h> #include <PluginStrategy.h> #include <VisitedLinkStrategy.h> namespace WebCore { class Page; +class PasteboardStrategy; } -class PlatformStrategiesQt : public WebCore::PlatformStrategies, private WebCore::CookiesStrategy, private WebCore::PluginStrategy, private WebCore::LocalizationStrategy, private WebCore::VisitedLinkStrategy { +class PlatformStrategiesQt : public WebCore::PlatformStrategies, private WebCore::CookiesStrategy, private WebCore::PluginStrategy, private WebCore::VisitedLinkStrategy { public: static void initialize(); @@ -48,8 +48,8 @@ private: // WebCore::PlatformStrategies virtual WebCore::CookiesStrategy* createCookiesStrategy(); virtual WebCore::PluginStrategy* createPluginStrategy(); - virtual WebCore::LocalizationStrategy* createLocalizationStrategy(); virtual WebCore::VisitedLinkStrategy* createVisitedLinkStrategy(); + virtual WebCore::PasteboardStrategy* createPasteboardStrategy(); // WebCore::CookiesStrategy virtual void notifyCookiesChanged(); @@ -58,101 +58,6 @@ private: virtual void refreshPlugins(); virtual void getPluginInfo(const WebCore::Page*, Vector<WebCore::PluginInfo>&); - // WebCore::LocalizationStrategy - virtual WTF::String inputElementAltText(); - virtual WTF::String resetButtonDefaultLabel(); - virtual WTF::String searchableIndexIntroduction(); - virtual WTF::String submitButtonDefaultLabel(); - virtual WTF::String fileButtonChooseFileLabel(); - virtual WTF::String fileButtonChooseMultipleFilesLabel(); - virtual WTF::String fileButtonNoFileSelectedLabel(); - virtual WTF::String fileButtonNoFilesSelectedLabel(); - virtual WTF::String defaultDetailsSummaryText(); - virtual WTF::String contextMenuItemTagOpenLinkInNewWindow(); - virtual WTF::String contextMenuItemTagDownloadLinkToDisk(); - virtual WTF::String contextMenuItemTagCopyLinkToClipboard(); - virtual WTF::String contextMenuItemTagOpenImageInNewWindow(); - virtual WTF::String contextMenuItemTagDownloadImageToDisk(); - virtual WTF::String contextMenuItemTagCopyImageToClipboard(); - virtual WTF::String contextMenuItemTagCopyImageUrlToClipboard(); - virtual WTF::String contextMenuItemTagOpenFrameInNewWindow(); - virtual WTF::String contextMenuItemTagCopy(); - virtual WTF::String contextMenuItemTagGoBack(); - virtual WTF::String contextMenuItemTagGoForward(); - virtual WTF::String contextMenuItemTagStop(); - virtual WTF::String contextMenuItemTagReload(); - virtual WTF::String contextMenuItemTagCut(); - virtual WTF::String contextMenuItemTagPaste(); - virtual WTF::String contextMenuItemTagSelectAll(); - virtual WTF::String contextMenuItemTagNoGuessesFound(); - virtual WTF::String contextMenuItemTagIgnoreSpelling(); - virtual WTF::String contextMenuItemTagLearnSpelling(); - virtual WTF::String contextMenuItemTagSearchWeb(); - virtual WTF::String contextMenuItemTagLookUpInDictionary(const String&); - virtual WTF::String contextMenuItemTagOpenLink(); - virtual WTF::String contextMenuItemTagIgnoreGrammar(); - virtual WTF::String contextMenuItemTagSpellingMenu(); - virtual WTF::String contextMenuItemTagShowSpellingPanel(bool show); - virtual WTF::String contextMenuItemTagCheckSpelling(); - virtual WTF::String contextMenuItemTagCheckSpellingWhileTyping(); - virtual WTF::String contextMenuItemTagCheckGrammarWithSpelling(); - virtual WTF::String contextMenuItemTagFontMenu(); - virtual WTF::String contextMenuItemTagBold(); - virtual WTF::String contextMenuItemTagItalic(); - virtual WTF::String contextMenuItemTagUnderline(); - virtual WTF::String contextMenuItemTagOutline(); - virtual WTF::String contextMenuItemTagWritingDirectionMenu(); - virtual WTF::String contextMenuItemTagTextDirectionMenu(); - virtual WTF::String contextMenuItemTagDefaultDirection(); - virtual WTF::String contextMenuItemTagLeftToRight(); - virtual WTF::String contextMenuItemTagRightToLeft(); - virtual WTF::String contextMenuItemTagInspectElement(); - virtual WTF::String contextMenuItemTagOpenVideoInNewWindow(); - virtual WTF::String contextMenuItemTagOpenAudioInNewWindow(); - virtual WTF::String contextMenuItemTagCopyVideoLinkToClipboard(); - virtual WTF::String contextMenuItemTagCopyAudioLinkToClipboard(); - virtual WTF::String contextMenuItemTagToggleMediaControls(); - virtual WTF::String contextMenuItemTagToggleMediaLoop(); - virtual WTF::String contextMenuItemTagEnterVideoFullscreen(); - virtual WTF::String contextMenuItemTagMediaPlay(); - virtual WTF::String contextMenuItemTagMediaPause(); - virtual WTF::String contextMenuItemTagMediaMute(); - virtual WTF::String searchMenuNoRecentSearchesText(); - virtual WTF::String searchMenuRecentSearchesText(); - virtual WTF::String searchMenuClearRecentSearchesText(); - virtual WTF::String AXWebAreaText(); - virtual WTF::String AXLinkText(); - virtual WTF::String AXListMarkerText(); - virtual WTF::String AXImageMapText(); - virtual WTF::String AXHeadingText(); - virtual WTF::String AXDefinitionListTermText(); - virtual WTF::String AXDefinitionListDefinitionText(); - virtual WTF::String AXButtonActionVerb(); - virtual WTF::String AXRadioButtonActionVerb(); - virtual WTF::String AXTextFieldActionVerb(); - virtual WTF::String AXCheckedCheckBoxActionVerb(); - virtual WTF::String AXUncheckedCheckBoxActionVerb(); - virtual WTF::String AXMenuListActionVerb(); - virtual WTF::String AXMenuListPopupActionVerb(); - virtual WTF::String AXLinkActionVerb(); - virtual WTF::String missingPluginText(); - virtual WTF::String crashedPluginText(); - virtual WTF::String multipleFileUploadText(unsigned numberOfFiles); - virtual WTF::String unknownFileSizeText(); - virtual WTF::String imageTitle(const WTF::String& filename, const WebCore::IntSize&); - virtual WTF::String mediaElementLoadingStateText(); - virtual WTF::String mediaElementLiveBroadcastStateText(); - virtual WTF::String localizedMediaControlElementString(const WTF::String&); - virtual WTF::String localizedMediaControlElementHelpText(const WTF::String&); - virtual WTF::String localizedMediaTimeDescription(float); - virtual WTF::String validationMessageValueMissingText(); - virtual WTF::String validationMessageTypeMismatchText(); - virtual WTF::String validationMessagePatternMismatchText(); - virtual WTF::String validationMessageTooLongText(); - virtual WTF::String validationMessageRangeUnderflowText(); - virtual WTF::String validationMessageRangeOverflowText(); - virtual WTF::String validationMessageStepMismatchText(); - // WebCore::VisitedLinkStrategy virtual bool isLinkVisited(WebCore::Page*, WebCore::LinkHash, const WebCore::KURL& baseURL, const WTF::AtomicString& attributeURL); virtual void addVisitedLink(WebCore::Page*, WebCore::LinkHash); diff --git a/Source/WebKit/qt/WebCoreSupport/TextCheckerClientQt.h b/Source/WebKit/qt/WebCoreSupport/TextCheckerClientQt.h index e78ce1d10..ae419b250 100644 --- a/Source/WebKit/qt/WebCoreSupport/TextCheckerClientQt.h +++ b/Source/WebKit/qt/WebCoreSupport/TextCheckerClientQt.h @@ -47,7 +47,7 @@ public: virtual String getAutoCorrectSuggestionForMisspelledWord(const String& misspelledWord); virtual void checkGrammarOfString(const UChar*, int length, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength); virtual void getGuessesForWord(const String& word, const String& context, Vector<String>& guesses); - virtual void requestCheckingOfString(SpellChecker*, int, TextCheckingTypeMask, const String&) { } + virtual void requestCheckingOfString(SpellChecker*, const TextCheckingRequest&) { } virtual bool isContinousSpellCheckingEnabled(); virtual void toggleContinousSpellChecking(); diff --git a/Source/WebKit/qt/WebCoreSupport/WebEventConversion.cpp b/Source/WebKit/qt/WebCoreSupport/WebEventConversion.cpp new file mode 100644 index 000000000..be5f5298e --- /dev/null +++ b/Source/WebKit/qt/WebCoreSupport/WebEventConversion.cpp @@ -0,0 +1,237 @@ +/* + Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2006 Zack Rusin <zack@kde.org> + Copyright (C) 2011 Research In Motion Limited. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "WebEventConversion.h" + +#include "PlatformMouseEvent.h" +#include "PlatformWheelEvent.h" +#include <QApplication> +#include <QGraphicsSceneMouseEvent> +#include <QWheelEvent> +#include <wtf/CurrentTime.h> + +namespace WebCore { + +static void mouseEventModifiersFromQtKeyboardModifiers(Qt::KeyboardModifiers keyboardModifiers, unsigned& modifiers) +{ + modifiers = 0; + if (keyboardModifiers & Qt::ShiftModifier) + modifiers |= PlatformEvent::ShiftKey; + if (keyboardModifiers & Qt::ControlModifier) + modifiers |= PlatformEvent::CtrlKey; + if (keyboardModifiers & Qt::AltModifier) + modifiers |= PlatformEvent::AltKey; + if (keyboardModifiers & Qt::MetaModifier) + modifiers |= PlatformEvent::MetaKey; +} + +static void mouseEventTypeAndMouseButtonFromQEvent(const QEvent* event, PlatformEvent::Type& mouseEventType, MouseButton& mouseButton) +{ + enum { MouseEvent, GraphicsSceneMouseEvent } frameworkMouseEventType; + switch (event->type()) { + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonPress: + frameworkMouseEventType = MouseEvent; + mouseEventType = PlatformEvent::MousePressed; + break; + case QEvent::MouseButtonRelease: + frameworkMouseEventType = MouseEvent; + mouseEventType = PlatformEvent::MouseReleased; + break; + case QEvent::MouseMove: + frameworkMouseEventType = MouseEvent; + mouseEventType = PlatformEvent::MouseMoved; + break; + case QEvent::GraphicsSceneMouseDoubleClick: + case QEvent::GraphicsSceneMousePress: + frameworkMouseEventType = GraphicsSceneMouseEvent; + mouseEventType = PlatformEvent::MousePressed; + break; + case QEvent::GraphicsSceneMouseRelease: + frameworkMouseEventType = GraphicsSceneMouseEvent; + mouseEventType = PlatformEvent::MouseReleased; + break; + case QEvent::GraphicsSceneMouseMove: + frameworkMouseEventType = GraphicsSceneMouseEvent; + mouseEventType = PlatformEvent::MouseMoved; + break; + default: + ASSERT_NOT_REACHED(); + frameworkMouseEventType = MouseEvent; + mouseEventType = PlatformEvent::MouseMoved; + break; + } + + Qt::MouseButtons mouseButtons; + switch (frameworkMouseEventType) { + case MouseEvent: { + const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event); + mouseButtons = mouseEventType == PlatformEvent::MouseMoved ? mouseEvent->buttons() : mouseEvent->button(); + break; + } + case GraphicsSceneMouseEvent: { + const QGraphicsSceneMouseEvent* mouseEvent = static_cast<const QGraphicsSceneMouseEvent*>(event); + mouseButtons = mouseEventType == PlatformEvent::MouseMoved ? mouseEvent->buttons() : mouseEvent->button(); + break; + } + } + + if (mouseButtons & Qt::LeftButton) + mouseButton = LeftButton; + else if (mouseButtons & Qt::RightButton) + mouseButton = RightButton; + else if (mouseButtons & Qt::MidButton) + mouseButton = MiddleButton; + else + mouseButton = NoButton; +} + +class WebKitPlatformMouseEvent : public PlatformMouseEvent { +public: + WebKitPlatformMouseEvent(QGraphicsSceneMouseEvent*, int clickCount); + WebKitPlatformMouseEvent(QInputEvent*, int clickCount); +}; + +WebKitPlatformMouseEvent::WebKitPlatformMouseEvent(QGraphicsSceneMouseEvent* event, int clickCount) +{ + m_timestamp = WTF::currentTime(); + + // FIXME: Why don't we handle a context menu event here as we do in PlatformMouseEvent(QInputEvent*, int)? + // See <https://bugs.webkit.org/show_bug.cgi?id=60728>. + PlatformEvent::Type type; + mouseEventTypeAndMouseButtonFromQEvent(event, type, m_button); + + m_type = type; + m_position = IntPoint(event->pos().toPoint()); + m_globalPosition = IntPoint(event->screenPos()); + + m_clickCount = clickCount; + mouseEventModifiersFromQtKeyboardModifiers(event->modifiers(), m_modifiers); +} + +WebKitPlatformMouseEvent::WebKitPlatformMouseEvent(QInputEvent* event, int clickCount) +{ + m_timestamp = WTF::currentTime(); + + bool isContextMenuEvent = false; +#ifndef QT_NO_CONTEXTMENU + if (event->type() == QEvent::ContextMenu) { + isContextMenuEvent = true; + m_type = PlatformEvent::MousePressed; + QContextMenuEvent* ce = static_cast<QContextMenuEvent*>(event); + m_position = IntPoint(ce->pos()); + m_globalPosition = IntPoint(ce->globalPos()); + m_button = RightButton; + } +#endif + if (!isContextMenuEvent) { + PlatformEvent::Type type; + mouseEventTypeAndMouseButtonFromQEvent(event, type, m_button); + QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event); + + m_type = type; + m_position = IntPoint(mouseEvent->pos()); + m_globalPosition = IntPoint(mouseEvent->globalPos()); + } + + m_clickCount = clickCount; + mouseEventModifiersFromQtKeyboardModifiers(event->modifiers(), m_modifiers); +} + +PlatformMouseEvent convertMouseEvent(QInputEvent* event, int clickCount) +{ + return WebKitPlatformMouseEvent(event, clickCount); +} + +PlatformMouseEvent convertMouseEvent(QGraphicsSceneMouseEvent* event, int clickCount) +{ + return WebKitPlatformMouseEvent(event, clickCount); +} + +class WebKitPlatformWheelEvent : public PlatformWheelEvent { +public: + WebKitPlatformWheelEvent(QGraphicsSceneWheelEvent*); + WebKitPlatformWheelEvent(QWheelEvent*); + +private: + void applyDelta(int delta, Qt::Orientation); +}; + +void WebKitPlatformWheelEvent::applyDelta(int delta, Qt::Orientation orientation) +{ + // A delta that is not mod 120 indicates a device that is sending + // fine-resolution scroll events, so use the delta as number of wheel ticks + // and number of pixels to scroll.See also webkit.org/b/29601 + bool fullTick = !(delta % 120); + + if (orientation == Qt::Horizontal) { + m_deltaX = (fullTick) ? delta / 120.0f : delta; + m_deltaY = 0; + } else { + m_deltaX = 0; + m_deltaY = (fullTick) ? delta / 120.0f : delta; + } + + m_wheelTicksX = m_deltaX; + m_wheelTicksY = m_deltaY; + + // Use the same single scroll step as QTextEdit + // (in QTextEditPrivate::init [h,v]bar->setSingleStep) + static const float cDefaultQtScrollStep = 20.f; + m_deltaX *= (fullTick) ? QApplication::wheelScrollLines() * cDefaultQtScrollStep : 1; + m_deltaY *= (fullTick) ? QApplication::wheelScrollLines() * cDefaultQtScrollStep : 1; +} + +WebKitPlatformWheelEvent::WebKitPlatformWheelEvent(QGraphicsSceneWheelEvent* e) +{ + m_timestamp = WTF::currentTime(); + mouseEventModifiersFromQtKeyboardModifiers(e->modifiers(), m_modifiers); + m_position = e->pos().toPoint(); + m_globalPosition = e->screenPos(); + m_granularity = ScrollByPixelWheelEvent; + m_directionInvertedFromDevice = false; + applyDelta(e->delta(), e->orientation()); +} + +WebKitPlatformWheelEvent::WebKitPlatformWheelEvent(QWheelEvent* e) +{ + m_timestamp = WTF::currentTime(); + mouseEventModifiersFromQtKeyboardModifiers(e->modifiers(), m_modifiers); + m_position = e->pos(); + m_globalPosition = e->globalPos(); + m_granularity = ScrollByPixelWheelEvent; + m_directionInvertedFromDevice = false; + applyDelta(e->delta(), e->orientation()); +} + + +PlatformWheelEvent convertWheelEvent(QWheelEvent* event) +{ + return WebKitPlatformWheelEvent(event); +} + +PlatformWheelEvent convertWheelEvent(QGraphicsSceneWheelEvent* event) +{ + return WebKitPlatformWheelEvent(event); +} + +} diff --git a/Source/WebKit/qt/WebCoreSupport/WebEventConversion.h b/Source/WebKit/qt/WebCoreSupport/WebEventConversion.h new file mode 100644 index 000000000..25d02df22 --- /dev/null +++ b/Source/WebKit/qt/WebCoreSupport/WebEventConversion.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2006 Zack Rusin <zack@kde.org> + Copyright (C) 2011 Research In Motion Limited. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qglobal.h> + +QT_BEGIN_NAMESPACE +class QInputEvent; +class QGraphicsSceneMouseEvent; +class QWheelEvent; +class QGraphicsSceneWheelEvent; +QT_END_NAMESPACE + +namespace WebCore { + +class PlatformMouseEvent; +class PlatformWheelEvent; + +PlatformMouseEvent convertMouseEvent(QInputEvent*, int clickCount); +PlatformMouseEvent convertMouseEvent(QGraphicsSceneMouseEvent*, int clickCount); +PlatformWheelEvent convertWheelEvent(QWheelEvent*); +PlatformWheelEvent convertWheelEvent(QGraphicsSceneWheelEvent*); + +} diff --git a/Source/WebKit/qt/declarative/experimental/plugin.cpp b/Source/WebKit/qt/declarative/experimental/plugin.cpp index 7a41657ac..da228521f 100644 --- a/Source/WebKit/qt/declarative/experimental/plugin.cpp +++ b/Source/WebKit/qt/declarative/experimental/plugin.cpp @@ -46,6 +46,9 @@ class WebKitQmlExperimentalExtensionPlugin: public QDeclarativeExtensionPlugin { public: virtual void registerTypes(const char* uri) { + qWarning("\nWARNING: This project is using the experimental QML API extensions for QtWebKit and is therefore tied to a specific QtWebKit release.\n" + "WARNING: The experimental API will change from version to version, or even be removed. You have been warned!\n"); + Q_ASSERT(QLatin1String(uri) == QLatin1String("QtWebKit.experimental")); qmlRegisterUncreatableType<QWebDownloadItem>(uri, 1, 0, "DownloadItem", QObject::tr("Cannot create separate instance of DownloadItem")); diff --git a/Source/WebKit/qt/declarative/plugin.cpp b/Source/WebKit/qt/declarative/plugin.cpp index 64638e469..e2f0fb3ec 100644 --- a/Source/WebKit/qt/declarative/plugin.cpp +++ b/Source/WebKit/qt/declarative/plugin.cpp @@ -25,6 +25,7 @@ #if defined(HAVE_WEBKIT2) #include "qquickwebpage_p.h" #include "qquickwebview_p.h" +#include "qtwebsecurityorigin_p.h" #include "qwebiconimageprovider_p.h" #include "qwebnavigationrequest_p.h" #include "qwebpermissionrequest_p.h" @@ -65,6 +66,8 @@ public: qmlRegisterUncreatableType<QNetworkReply>(uri, 3, 0, "NetworkReply", QObject::tr("Cannot create separate instance of NetworkReply")); qmlRegisterUncreatableType<QWebPermissionRequest>(uri, 3, 0, "PermissionRequest", QObject::tr("Cannot create separate instance of PermissionRequest")); qmlRegisterUncreatableType<QWebNavigationRequest>(uri, 3, 0, "NavigationRequest", QObject::tr("Cannot create separate instance of NavigationRequest")); + qmlRegisterUncreatableType<QtWebSecurityOrigin>(uri, 3, 0, "SecurityOrigin", QObject::tr("Cannot create separate instance of SecurityOrigin")); + #endif } }; diff --git a/Source/WebKit/qt/tests/benchmarks/loading/tst_loading.cpp b/Source/WebKit/qt/tests/benchmarks/loading/tst_loading.cpp index 661a7e3cb..1c3985b83 100644 --- a/Source/WebKit/qt/tests/benchmarks/loading/tst_loading.cpp +++ b/Source/WebKit/qt/tests/benchmarks/loading/tst_loading.cpp @@ -25,28 +25,7 @@ #include <qwebview.h> #include <qpainter.h> -/** - * Starts an event loop that runs until the given signal is received. - Optionally the event loop - * can return earlier on a timeout. - * - * \return \p true if the requested signal was received - * \p false on timeout - */ -static bool waitForSignal(QObject* obj, const char* signal, int timeout = 0) -{ - QEventLoop loop; - QObject::connect(obj, signal, &loop, SLOT(quit())); - QTimer timer; - QSignalSpy timeoutSpy(&timer, SIGNAL(timeout())); - if (timeout > 0) { - QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); - timer.setSingleShot(true); - timer.start(timeout); - } - loop.exec(); - return timeoutSpy.isEmpty(); -} +#include "util.h" class tst_Loading : public QObject { @@ -96,13 +75,13 @@ void tst_Loading::load() QFETCH(QUrl, url); if (!m_manager.isOnline()) - QSKIP("This test requires an active network connection", SkipSingle); + W_QSKIP("This test requires an active network connection", SkipSingle); QBENCHMARK { m_view->load(url); // really wait for loading, painting is in another test - ::waitForSignal(m_view, SIGNAL(loadFinished(bool))); + ::waitForSignal(m_view, SIGNAL(loadFinished(bool)), 0); } } diff --git a/Source/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp b/Source/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp index 47d34dcbd..3f97b5aea 100644 --- a/Source/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp +++ b/Source/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp @@ -26,28 +26,7 @@ #include <qwebview.h> #include <qpainter.h> -/** - * Starts an event loop that runs until the given signal is received. - Optionally the event loop - * can return earlier on a timeout. - * - * \return \p true if the requested signal was received - * \p false on timeout - */ -static bool waitForSignal(QObject* obj, const char* signal, int timeout = 0) -{ - QEventLoop loop; - QObject::connect(obj, signal, &loop, SLOT(quit())); - QTimer timer; - QSignalSpy timeoutSpy(&timer, SIGNAL(timeout())); - if (timeout > 0) { - QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); - timer.setSingleShot(true); - timer.start(timeout); - } - loop.exec(); - return timeoutSpy.isEmpty(); -} +#include "util.h" class tst_Painting : public QObject { @@ -96,10 +75,10 @@ void tst_Painting::paint() QFETCH(QUrl, url); if (!m_manager.isOnline()) - QSKIP("This test requires an active network connection", SkipSingle); + W_QSKIP("This test requires an active network connection", SkipSingle); m_view->load(url); - ::waitForSignal(m_view, SIGNAL(loadFinished(bool))); + ::waitForSignal(m_view, SIGNAL(loadFinished(bool)), 0); /* force a layout */ QWebFrame* mainFrame = m_page->mainFrame(); @@ -116,7 +95,7 @@ void tst_Painting::paint() void tst_Painting::textAreas() { m_view->load(QUrl("data:text/html;<html><body></body></html>")); - ::waitForSignal(m_view, SIGNAL(loadFinished(bool))); + ::waitForSignal(m_view, SIGNAL(loadFinished(bool)), 0); QWebElement bodyElement = m_page->mainFrame()->findFirstElement("body"); diff --git a/Source/WebKit/qt/tests/qdeclarativewebview/tst_qdeclarativewebview.cpp b/Source/WebKit/qt/tests/qdeclarativewebview/tst_qdeclarativewebview.cpp index 1f9a2ff84..f9421e3cf 100644 --- a/Source/WebKit/qt/tests/qdeclarativewebview/tst_qdeclarativewebview.cpp +++ b/Source/WebKit/qt/tests/qdeclarativewebview/tst_qdeclarativewebview.cpp @@ -139,7 +139,7 @@ void tst_QDeclarativeWebView::basicProperties() void tst_QDeclarativeWebView::elementAreaAt() { - QSKIP("This test should be changed to test 'heuristicZoom' instead.", SkipAll); + W_QSKIP("This test should be changed to test 'heuristicZoom' instead.", SkipAll); QDeclarativeEngine engine; QDeclarativeComponent component(&engine, QUrl("qrc:///resources/elements.qml")); checkNoErrors(component); diff --git a/Source/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp b/Source/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp index 3eb08c450..2c28aef1f 100644 --- a/Source/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp +++ b/Source/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp @@ -2555,7 +2555,7 @@ void tst_QWebFrame::setHtmlWithBaseURL() // As we are using a local file as baseUrl, its security origin should be able to load local resources. if (!QDir(TESTS_SOURCE_DIR).exists()) - QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll); + W_QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll); QDir::setCurrent(TESTS_SOURCE_DIR); diff --git a/Source/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp b/Source/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp index b3ff3b9c1..b6f0aeee3 100644 --- a/Source/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp +++ b/Source/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp @@ -160,7 +160,9 @@ private slots: void testStopScheduledPageRefresh(); void findText(); void supportedContentType(); - void infiniteLoopJS(); + // [Qt] tst_QWebPage::infiniteLoopJS() timeouts with DFG JIT + // https://bugs.webkit.org/show_bug.cgi?id=79040 + // void infiniteLoopJS(); void navigatorCookieEnabled(); void deleteQWebViewTwice(); void renderOnRepaintRequestedShouldNotRecurse(); @@ -284,6 +286,9 @@ private: bool m_allowGeolocation; }; +// [Qt] tst_QWebPage::infiniteLoopJS() timeouts with DFG JIT +// https://bugs.webkit.org/show_bug.cgi?id=79040 +/* void tst_QWebPage::infiniteLoopJS() { JSTestPage* newPage = new JSTestPage(m_view); @@ -292,6 +297,7 @@ void tst_QWebPage::infiniteLoopJS() m_view->page()->mainFrame()->evaluateJavaScript("var run = true;var a = 1;while(run){a++;}"); delete newPage; } +*/ void tst_QWebPage::geolocationRequestJS() { @@ -299,7 +305,7 @@ void tst_QWebPage::geolocationRequestJS() if (newPage->mainFrame()->evaluateJavaScript(QLatin1String("!navigator.geolocation")).toBool()) { delete newPage; - QSKIP("Geolocation is not supported.", SkipSingle); + W_QSKIP("Geolocation is not supported.", SkipSingle); } connect(newPage, SIGNAL(featurePermissionRequested(QWebFrame*, QWebPage::Feature)), @@ -529,7 +535,7 @@ void tst_QWebPage::loadHtml5Video() QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=65452", Continue); QCOMPARE(mUrl.toEncoded(), url); #else - QSKIP("This test requires Qt Multimedia", SkipAll); + W_QSKIP("This test requires Qt Multimedia", SkipAll); #endif } @@ -2738,7 +2744,7 @@ void tst_QWebPage::screenshot_data() void tst_QWebPage::screenshot() { if (!QDir(TESTS_SOURCE_DIR).exists()) - QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll); + W_QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll); QDir::setCurrent(TESTS_SOURCE_DIR); diff --git a/Source/WebKit/qt/tests/qwebview/tst_qwebview.cpp b/Source/WebKit/qt/tests/qwebview/tst_qwebview.cpp index be2c4c985..f7dc9c5f4 100644 --- a/Source/WebKit/qt/tests/qwebview/tst_qwebview.cpp +++ b/Source/WebKit/qt/tests/qwebview/tst_qwebview.cpp @@ -133,7 +133,7 @@ void tst_QWebView::reusePage_data() void tst_QWebView::reusePage() { if (!QDir(TESTS_SOURCE_DIR).exists()) - QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll); + W_QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll); QDir::setCurrent(TESTS_SOURCE_DIR); diff --git a/Source/WebKit/qt/tests/util.h b/Source/WebKit/qt/tests/util.h index 94628ca9c..22192bad2 100644 --- a/Source/WebKit/qt/tests/util.h +++ b/Source/WebKit/qt/tests/util.h @@ -77,4 +77,9 @@ static bool waitForSignal(QObject* obj, const char* signal, int timeout = 10000) } \ QCOMPARE(__expr, __expected); \ } while(0) + +// Compatibility for Qt5 +#define W_QSKIP(a, b) QSKIP(a, b) +#else +#define W_QSKIP(a, b) QSKIP(a) #endif diff --git a/Source/WebKit/win/ChangeLog b/Source/WebKit/win/ChangeLog index 32db318fa..1c7f320a2 100644 --- a/Source/WebKit/win/ChangeLog +++ b/Source/WebKit/win/ChangeLog @@ -1,3 +1,138 @@ +2012-02-24 Shinya Kawanaka <shinyak@chromium.org> + + SpellCheckRequest needs to know the context where the spellcheck happened. + https://bugs.webkit.org/show_bug.cgi?id=79320 + + Reviewed by Hajime Morita. + + * WebCoreSupport/WebEditorClient.h: + (WebEditorClient::requestCheckingOfString): + (WebEditorClient): + +2012-02-21 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/WebEditorClient.cpp: + (WebEditorClient::shouldApplyStyle): + * WebCoreSupport/WebEditorClient.h: + (WebEditorClient): + +2012-02-22 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/WebEditorClient.cpp: + (WebEditorClient::shouldApplyStyle): + * WebCoreSupport/WebEditorClient.h: + (WebEditorClient): + +2012-02-17 Kalev Lember <kalevlember@gmail.com> + + Remove unused parameters from WTF threading API + https://bugs.webkit.org/show_bug.cgi?id=78389 + + Reviewed by Adam Roben. + + waitForThreadCompletion() had an out param 'void **result' to get the + 'void *' returned by ThreadFunction. However, the implementation in + ThreadingWin.cpp ignored the out param, not filling it in. This had + led to a situation where none of the client code made use of the param + and just ignored it. + + To clean this up, the patch changes the signature of ThreadFunction to + return void instead of void* and drops the the unused 'void **result' + parameter from waitForThreadCompletion. Also, all client code is + updated for the API change. + + As mentioned in https://bugs.webkit.org/show_bug.cgi?id=78389 , even + though the change only affects internal API, Safari is using it + directly and we'll need to keep the old versions around for ABI + compatibility. For this, the patch adds compatibility wrappers with + the old ABI. + + * WebKit.vcproj/WebKit_Cairo.def: Add the new functions. + * WebKit.vcproj/WebKit_Cairo_debug.def: Ditto. + +2012-02-15 Sadrul Habib Chowdhury <sadrul@chromium.org> + + Notify ChromeClient when touch-event handlers are installed/removed. + https://bugs.webkit.org/show_bug.cgi?id=77440 + + Reviewed by Darin Fisher and Ryosuke Niwa. + + * WebCoreSupport/WebChromeClient.h: + (WebChromeClient::numTouchEventHandlersChanged): + +2012-02-14 Alexey Proskuryakov <ap@apple.com> + + [Mac][Win][WK2] Switch to RFC 6455 protocol for WebSockets + https://bugs.webkit.org/show_bug.cgi?id=78541 + <rdar://problem/10036695> + + Reviewed by Kent Tamura. + + * WebPreferences.cpp: (WebPreferences::initializeDefaultSettings): Changed default value of + the preference + +2012-02-11 Nikolas Zimmermann <nzimmermann@rim.com> + + Convert svg/animations to use SMIL methods for driving the timeline + https://bugs.webkit.org/show_bug.cgi?id=78422 + + Reviewed by Dirk Schulze. + + Remove SVG animation sampling functionality provided for DRT, which no longer uses it. + Instead we switched the svg/animations tests to use SVGSVGElement.setCurrentTime. + + * Interfaces/IWebFramePrivate.idl: + * WebFrame.cpp: + * WebFrame.h: + +2012-02-13 Andy Estes <aestes@apple.com> + + Fix the Windows build. + + * WebCoreSupport/WebPlatformStrategies.cpp: + (WebPlatformStrategies::createPasteboardStrategy): + * WebCoreSupport/WebPlatformStrategies.h: + (WebPlatformStrategies): + +2012-02-12 Andy Estes <aestes@apple.com> + + [Windows] Add API to enable inverted color drawing on a WebView + https://bugs.webkit.org/show_bug.cgi?id=77382 + + Reviewed by Adam Roben. + + Add a new private WebPreference key called "WebKitShouldInvertColors" + and add private cover methods to get and set the preference. When this + preference changes on a WebPreference object, all WebViews listening to + that object will repaint to reflect the new value. + + * Interfaces/IWebPreferencesPrivate.idl: Add [setS|s]houldInvertColors() + cover methods for WebKitShouldInvertColorsPreferenceKey. + * WebPreferenceKeysPrivate.h: Add WebKitShouldInvertColorsPreferenceKey. + * WebPreferences.cpp: + (WebPreferences::shouldInvertColors): + (WebPreferences::setShouldInvertColors): + * WebPreferences.h: + (WebPreferences): + * WebView.cpp: + (WebView::setShouldInvertColors): If m_shouldInvertColors changes, + update the value on the WebView and in m_layerTreeHost, then repaint + the view. + (WebView::notifyPreferencesChanged): + (WebView::setAcceleratedCompositing): When creating a new layer tree + host, tell it whether it should be inverting colors. + * WebView.h: + 2012-02-07 MORITA Hajime <morrita@google.com> Replacement text should be available from the marker. diff --git a/Source/WebKit/win/Interfaces/IWebFramePrivate.idl b/Source/WebKit/win/Interfaces/IWebFramePrivate.idl index 31287ba58..90ba4bdb9 100644 --- a/Source/WebKit/win/Interfaces/IWebFramePrivate.idl +++ b/Source/WebKit/win/Interfaces/IWebFramePrivate.idl @@ -98,8 +98,6 @@ interface IWebFramePrivate : IUnknown HRESULT counterValueForElementById([in] BSTR id, [out, retval] BSTR* result); - HRESULT pauseSVGAnimation([in] BSTR elementId, [in] IDOMNode* node, [in] double secondsFromNow, [out, retval] BOOL* animationWasRunning); - HRESULT visibleContentRect([out, retval] RECT*); HRESULT pageNumberForElementById([in] BSTR id, [in] float pageWidthInPixels, [in] float pageHeightInPixels, [out, retval] int* pageNumber); diff --git a/Source/WebKit/win/Interfaces/IWebPreferencesPrivate.idl b/Source/WebKit/win/Interfaces/IWebPreferencesPrivate.idl index 01ace36d7..ad67a56b0 100644 --- a/Source/WebKit/win/Interfaces/IWebPreferencesPrivate.idl +++ b/Source/WebKit/win/Interfaces/IWebPreferencesPrivate.idl @@ -140,4 +140,6 @@ interface IWebPreferencesPrivate : IUnknown HRESULT setShowsToolTipOverTruncatedText([in] BOOL); HRESULT showsToolTipOverTruncatedText([out, retval] BOOL*); + HRESULT setShouldInvertColors([in] BOOL); + HRESULT shouldInvertColors([out, retval] BOOL*); } diff --git a/Source/WebKit/win/WebCoreSupport/WebChromeClient.h b/Source/WebKit/win/WebCoreSupport/WebChromeClient.h index b6aeb1cf7..2a9a8fe7f 100644 --- a/Source/WebKit/win/WebCoreSupport/WebChromeClient.h +++ b/Source/WebKit/win/WebCoreSupport/WebChromeClient.h @@ -177,6 +177,7 @@ public: virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; } virtual void numWheelEventHandlersChanged(unsigned) { } + virtual void numTouchEventHandlersChanged(unsigned) { } private: COMPtr<IWebUIDelegate> uiDelegate(); diff --git a/Source/WebKit/win/WebCoreSupport/WebEditorClient.cpp b/Source/WebKit/win/WebCoreSupport/WebEditorClient.cpp index 0b2653095..6a4ee8476 100644 --- a/Source/WebKit/win/WebCoreSupport/WebEditorClient.cpp +++ b/Source/WebKit/win/WebCoreSupport/WebEditorClient.cpp @@ -276,13 +276,13 @@ bool WebEditorClient::shouldInsertText(const String& /*str*/, Range* /* replacin //bool WebEditorClient::shouldChangeSelectedRange(Range *currentRange, Range *toProposedRange, SelectionAffinity selectionAffinity, bool stillSelecting) //{ notImplemented(); return false; } -bool WebEditorClient::shouldApplyStyle(CSSStyleDeclaration* /*style*/, Range* /*toElementsInDOMRange*/) +bool WebEditorClient::shouldApplyStyle(StylePropertySet* /*style*/, Range* /*toElementsInDOMRange*/) { notImplemented(); return true; } bool WebEditorClient::shouldMoveRangeAfterDelete(Range* /*range*/, Range* /*rangeToBeReplaced*/) { notImplemented(); return true; } -bool WebEditorClient::shouldChangeTypingStyle(CSSStyleDeclaration* /*currentStyle*/, CSSStyleDeclaration* /*toProposedStyle*/) +bool WebEditorClient::shouldChangeTypingStyle(StylePropertySet* /*currentStyle*/, StylePropertySet* /*toProposedStyle*/) { notImplemented(); return false; } void WebEditorClient::webViewDidChangeTypingStyle(WebNotification* /*notification*/) diff --git a/Source/WebKit/win/WebCoreSupport/WebEditorClient.h b/Source/WebKit/win/WebCoreSupport/WebEditorClient.h index a40586c98..0f29e9e0f 100644 --- a/Source/WebKit/win/WebCoreSupport/WebEditorClient.h +++ b/Source/WebKit/win/WebCoreSupport/WebEditorClient.h @@ -64,9 +64,9 @@ public: bool shouldDeleteRange(WebCore::Range*); bool shouldInsertNode(WebCore::Node*, WebCore::Range* replacingRange, WebCore::EditorInsertAction); - bool shouldApplyStyle(WebCore::CSSStyleDeclaration*, WebCore::Range*); + bool shouldApplyStyle(WebCore::StylePropertySet*, WebCore::Range*); bool shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*); - bool shouldChangeTypingStyle(WebCore::CSSStyleDeclaration* currentStyle, WebCore::CSSStyleDeclaration* toProposedStyle); + bool shouldChangeTypingStyle(WebCore::StylePropertySet* currentStyle, WebCore::StylePropertySet* toProposedStyle); void webViewDidChangeTypingStyle(WebNotification*); void webViewDidChangeSelection(WebNotification*); @@ -110,7 +110,8 @@ public: virtual void willSetInputMethodState(); virtual void setInputMethodState(bool); - virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&) {} + virtual void requestCheckingOfString(WebCore::SpellChecker*, const WebCore::TextCheckingRequest&) { } + virtual WebCore::TextCheckerClient* textChecker() { return this; } private: diff --git a/Source/WebKit/win/WebCoreSupport/WebPlatformStrategies.cpp b/Source/WebKit/win/WebCoreSupport/WebPlatformStrategies.cpp index 7a3febb92..230f3323f 100644 --- a/Source/WebKit/win/WebCoreSupport/WebPlatformStrategies.cpp +++ b/Source/WebKit/win/WebCoreSupport/WebPlatformStrategies.cpp @@ -57,6 +57,11 @@ VisitedLinkStrategy* WebPlatformStrategies::createVisitedLinkStrategy() return this; } +PasteboardStrategy* WebPlatformStrategies::createPasteboardStrategy() +{ + return 0; +} + void WebPlatformStrategies::notifyCookiesChanged() { } diff --git a/Source/WebKit/win/WebCoreSupport/WebPlatformStrategies.h b/Source/WebKit/win/WebCoreSupport/WebPlatformStrategies.h index 509de098b..274124213 100644 --- a/Source/WebKit/win/WebCoreSupport/WebPlatformStrategies.h +++ b/Source/WebKit/win/WebCoreSupport/WebPlatformStrategies.h @@ -42,6 +42,7 @@ private: virtual WebCore::CookiesStrategy* createCookiesStrategy(); virtual WebCore::PluginStrategy* createPluginStrategy(); virtual WebCore::VisitedLinkStrategy* createVisitedLinkStrategy(); + virtual WebCore::PasteboardStrategy* createPasteboardStrategy(); // WebCore::CookiesStrategy virtual void notifyCookiesChanged(); diff --git a/Source/WebKit/win/WebFrame.cpp b/Source/WebKit/win/WebFrame.cpp index f15d3efd5..3564bd986 100644 --- a/Source/WebKit/win/WebFrame.cpp +++ b/Source/WebKit/win/WebFrame.cpp @@ -93,8 +93,6 @@ #include <WebCore/RenderView.h> #include <WebCore/RenderTreeAsText.h> #include <WebCore/Settings.h> -#include <WebCore/SVGDocumentExtensions.h> -#include <WebCore/SVGSMILElement.h> #include <WebCore/TextIterator.h> #include <WebCore/JSDOMBinding.h> #include <WebCore/ScriptController.h> @@ -1276,34 +1274,6 @@ HRESULT WebFrame::pauseTransition(BSTR propertyName, IDOMNode* node, double seco return S_OK; } -HRESULT WebFrame::pauseSVGAnimation(BSTR elementId, IDOMNode* node, double secondsFromNow, BOOL* animationWasRunning) -{ - if (!node || !animationWasRunning) - return E_POINTER; - - *animationWasRunning = FALSE; - - Frame* frame = core(this); - if (!frame) - return E_FAIL; - - Document* document = frame->document(); - if (!document || !document->svgExtensions()) - return E_FAIL; - - COMPtr<DOMNode> domNode(Query, node); - if (!domNode || !SVGSMILElement::isSMILElement(domNode->node())) - return E_FAIL; - -#if ENABLE(SVG) - *animationWasRunning = document->accessSVGExtensions()->sampleAnimationAtTime(String(elementId, SysStringLen(elementId)), static_cast<SVGSMILElement*>(domNode->node()), secondsFromNow); -#else - *animationWasRunning = FALSE; -#endif - - return S_OK; -} - HRESULT WebFrame::visibleContentRect(RECT* rect) { if (!rect) diff --git a/Source/WebKit/win/WebFrame.h b/Source/WebKit/win/WebFrame.h index f777a3205..c6286b0d0 100644 --- a/Source/WebKit/win/WebFrame.h +++ b/Source/WebKit/win/WebFrame.h @@ -259,7 +259,6 @@ public: virtual HRESULT STDMETHODCALLTYPE pauseAnimation(BSTR animationName, IDOMNode*, double secondsFromNow, BOOL* animationWasRunning); virtual HRESULT STDMETHODCALLTYPE pauseTransition(BSTR propertyName, IDOMNode*, double secondsFromNow, BOOL* transitionWasRunning); - virtual HRESULT STDMETHODCALLTYPE pauseSVGAnimation(BSTR elementId, IDOMNode*, double secondsFromNow, BOOL* animationWasRunning); virtual HRESULT STDMETHODCALLTYPE numberOfActiveAnimations(UINT*); virtual HRESULT STDMETHODCALLTYPE suspendAnimations(); virtual HRESULT STDMETHODCALLTYPE resumeAnimations(); diff --git a/Source/WebKit/win/WebKit.vcproj/WebKit_Cairo.def b/Source/WebKit/win/WebKit.vcproj/WebKit_Cairo.def index 89b0a2a61..e4cd266ed 100644 --- a/Source/WebKit/win/WebKit.vcproj/WebKit_Cairo.def +++ b/Source/WebKit/win/WebKit.vcproj/WebKit_Cairo.def @@ -122,6 +122,7 @@ EXPORTS ?broadcast@ThreadCondition@WTF@@QAEXXZ ?callOnMainThread@WTF@@YAXP6AXPAX@Z0@Z ?createThread@WTF@@YAIP6APAXPAX@Z0PBD@Z + ?createThread@WTF@@YAIP6AXPAX@Z0PBD@Z ?currentThread@WTF@@YAIXZ ?detachThread@WTF@@YAXI@Z ?initializeMainThread@WTF@@YAXXZ @@ -139,5 +140,6 @@ EXPORTS ?unlockAtomicallyInitializedStaticMutex@WTF@@YAXXZ ?updateLayoutIgnorePendingStylesheets@Document@WebCore@@QAEXXZ ?wait@ThreadCondition@WTF@@QAEXAAVMutex@2@@Z + ?waitForThreadCompletion@WTF@@YAHI@Z ?waitForThreadCompletion@WTF@@YAHIPAPAX@Z ?createThread@WTF@@YAIP6APAXPAX@Z0@Z diff --git a/Source/WebKit/win/WebKit.vcproj/WebKit_Cairo_debug.def b/Source/WebKit/win/WebKit.vcproj/WebKit_Cairo_debug.def index 1b1b72df4..e4ac119c2 100644 --- a/Source/WebKit/win/WebKit.vcproj/WebKit_Cairo_debug.def +++ b/Source/WebKit/win/WebKit.vcproj/WebKit_Cairo_debug.def @@ -122,6 +122,7 @@ EXPORTS ?broadcast@ThreadCondition@WTF@@QAEXXZ ?callOnMainThread@WTF@@YAXP6AXPAX@Z0@Z ?createThread@WTF@@YAIP6APAXPAX@Z0PBD@Z + ?createThread@WTF@@YAIP6AXPAX@Z0PBD@Z ?currentThread@WTF@@YAIXZ ?detachThread@WTF@@YAXI@Z ?initializeMainThread@WTF@@YAXXZ @@ -139,5 +140,6 @@ EXPORTS ?unlockAtomicallyInitializedStaticMutex@WTF@@YAXXZ ?updateLayoutIgnorePendingStylesheets@Document@WebCore@@QAEXXZ ?wait@ThreadCondition@WTF@@QAEXAAVMutex@2@@Z + ?waitForThreadCompletion@WTF@@YAHI@Z ?waitForThreadCompletion@WTF@@YAHIPAPAX@Z ?createThread@WTF@@YAIP6APAXPAX@Z0@Z diff --git a/Source/WebKit/win/WebPreferenceKeysPrivate.h b/Source/WebKit/win/WebPreferenceKeysPrivate.h index 76eacffeb..468944657 100644 --- a/Source/WebKit/win/WebPreferenceKeysPrivate.h +++ b/Source/WebKit/win/WebPreferenceKeysPrivate.h @@ -83,6 +83,7 @@ #define WebKitPDFScaleFactorPreferenceKey "WebKitPDFScaleFactor" #define WebKitEditableLinkBehaviorPreferenceKey "WebKitEditableLinkBehavior" #define WebKitEditingBehaviorPreferenceKey "WebKitEditingBehavior" +#define WebKitShouldInvertColorsPreferenceKey "WebKitShouldInvertColors" // Window display is throttled to 60 frames per second if WebKitThrottleWindowDisplayPreferenceKey // is set to YES. The window display throttle is OFF by default for compatibility with Mac OS X diff --git a/Source/WebKit/win/WebPreferences.cpp b/Source/WebKit/win/WebPreferences.cpp index 39e4644c0..6f5ed8e7e 100644 --- a/Source/WebKit/win/WebPreferences.cpp +++ b/Source/WebKit/win/WebPreferences.cpp @@ -268,7 +268,7 @@ void WebPreferences::initializeDefaultSettings() CFDictionaryAddValue(defaults, CFSTR(WebKitMemoryInfoEnabledPreferenceKey), kCFBooleanFalse); CFDictionaryAddValue(defaults, CFSTR(WebKitHyperlinkAuditingEnabledPreferenceKey), kCFBooleanTrue); - CFDictionaryAddValue(defaults, CFSTR(WebKitHixie76WebSocketProtocolEnabledPreferenceKey), kCFBooleanTrue); + CFDictionaryAddValue(defaults, CFSTR(WebKitHixie76WebSocketProtocolEnabledPreferenceKey), kCFBooleanFalse); CFDictionaryAddValue(defaults, CFSTR(WebKitMediaPlaybackRequiresUserGesturePreferenceKey), kCFBooleanFalse); CFDictionaryAddValue(defaults, CFSTR(WebKitMediaPlaybackAllowsInlinePreferenceKey), kCFBooleanTrue); @@ -1639,6 +1639,21 @@ HRESULT WebPreferences::setShowsToolTipOverTruncatedText(BOOL showsToolTip) return S_OK; } +HRESULT WebPreferences::shouldInvertColors(BOOL* shouldInvertColors) +{ + if (!shouldInvertColors) + return E_POINTER; + + *shouldInvertColors = boolValueForKey(CFSTR(WebKitShouldInvertColorsPreferenceKey)); + return S_OK; +} + +HRESULT WebPreferences::setShouldInvertColors(BOOL shouldInvertColors) +{ + setBoolValue(CFSTR(WebKitShouldInvertColorsPreferenceKey), shouldInvertColors); + return S_OK; +} + void WebPreferences::willAddToWebView() { ++m_numWebViews; diff --git a/Source/WebKit/win/WebPreferences.h b/Source/WebKit/win/WebPreferences.h index 3878050bb..baf56ecd0 100644 --- a/Source/WebKit/win/WebPreferences.h +++ b/Source/WebKit/win/WebPreferences.h @@ -468,6 +468,9 @@ public: virtual HRESULT STDMETHODCALLTYPE showsToolTipOverTruncatedText(BOOL*); virtual HRESULT STDMETHODCALLTYPE setShowsToolTipOverTruncatedText(BOOL); + virtual HRESULT STDMETHODCALLTYPE shouldInvertColors(BOOL*); + virtual HRESULT STDMETHODCALLTYPE setShouldInvertColors(BOOL); + // WebPreferences // This method accesses a different preference key than developerExtrasEnabled. diff --git a/Source/WebKit/win/WebView.cpp b/Source/WebKit/win/WebView.cpp index 57acc1318..5927c9664 100644 --- a/Source/WebKit/win/WebView.cpp +++ b/Source/WebKit/win/WebView.cpp @@ -2072,6 +2072,23 @@ void WebView::setIsBeingDestroyed() ::SetWindowLongPtrW(m_viewWindow, 0, 0); } +void WebView::setShouldInvertColors(bool shouldInvertColors) +{ + if (m_shouldInvertColors == shouldInvertColors) + return; + + m_shouldInvertColors = shouldInvertColors; + +#if USE(ACCELERATED_COMPOSITING) + if (m_layerTreeHost) + m_layerTreeHost->setShouldInvertColors(shouldInvertColors); +#endif + + RECT windowRect = {0}; + frameRect(&windowRect); + repaint(windowRect, true, true); +} + bool WebView::registerWebViewWindowClass() { static bool haveRegisteredWindowClass = false; @@ -4922,6 +4939,11 @@ HRESULT WebView::notifyPreferencesChanged(IWebNotification* notification) return hr; settings->setMediaPlaybackAllowsInline(enabled); + hr = prefsPrivate->shouldInvertColors(&enabled); + if (FAILED(hr)) + return hr; + setShouldInvertColors(enabled); + return S_OK; } @@ -6463,6 +6485,8 @@ void WebView::setAcceleratedCompositing(bool accelerated) if (m_layerTreeHost) { m_isAcceleratedCompositing = true; + m_layerTreeHost->setShouldInvertColors(m_shouldInvertColors); + m_layerTreeHost->setClient(this); ASSERT(m_viewWindow); m_layerTreeHost->setWindow(m_viewWindow); diff --git a/Source/WebKit/win/WebView.h b/Source/WebKit/win/WebView.h index 7d2a6e2f9..30843d366 100644 --- a/Source/WebKit/win/WebView.h +++ b/Source/WebKit/win/WebView.h @@ -1002,6 +1002,7 @@ private: #endif bool m_shouldInvertColors; + void setShouldInvertColors(bool); protected: static bool registerWebViewWindowClass(); diff --git a/Source/WebKit/wince/ChangeLog b/Source/WebKit/wince/ChangeLog index 6d2a7e647..998f5d165 100644 --- a/Source/WebKit/wince/ChangeLog +++ b/Source/WebKit/wince/ChangeLog @@ -1,3 +1,70 @@ +2012-02-24 Shinya Kawanaka <shinyak@chromium.org> + + SpellCheckRequest needs to know the context where the spellcheck happened. + https://bugs.webkit.org/show_bug.cgi?id=79320 + + Reviewed by Hajime Morita. + + * WebCoreSupport/EditorClientWinCE.h: + (WebKit::EditorClientWinCE::requestCheckingOfString): + +2012-02-23 Patrick Gansterer <paroga@webkit.org> + + Unreviewed WinCE build fix after r108462. + + * WebCoreSupport/EditorClientWinCE.h: + (EditorClientWinCE): + +2012-02-21 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/EditorClientWinCE.cpp: + (WebKit::EditorClientWinCE::shouldApplyStyle): + +2012-02-22 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebCoreSupport/EditorClientWinCE.cpp: + (WebKit::EditorClientWinCE::shouldApplyStyle): + +2012-02-20 Benjamin Poulain <benjamin@webkit.org> + + Get rid of the LocalizationStrategy + https://bugs.webkit.org/show_bug.cgi?id=78324 + + Reviewed by Sam Weinig. + + Remove a useless #include of LocalizationStrategy.h. + + * WebCoreSupport/PlatformStrategiesWinCE.h: + +2012-02-15 Patrick Gansterer <paroga@webkit.org> + + Unreviewed WinCE build fix after r107606. + + * WebCoreSupport/PlatformStrategiesWinCE.cpp: + (PlatformStrategiesWinCE::createPasteboardStrategy): + * WebCoreSupport/PlatformStrategiesWinCE.h: + (PlatformStrategiesWinCE): + +2012-02-15 Sadrul Habib Chowdhury <sadrul@chromium.org> + + Notify ChromeClient when touch-event handlers are installed/removed. + https://bugs.webkit.org/show_bug.cgi?id=77440 + + Reviewed by Darin Fisher and Ryosuke Niwa. + + * WebCoreSupport/ChromeClientWinCE.h: + (WebKit::ChromeClientWinCE::numTouchEventHandlersChanged): + 2011-12-19 Sam Weinig <sam@webkit.org> More PlatformEvent cleanup diff --git a/Source/WebKit/wince/WebCoreSupport/ChromeClientWinCE.h b/Source/WebKit/wince/WebCoreSupport/ChromeClientWinCE.h index 006e010f8..613783a03 100644 --- a/Source/WebKit/wince/WebCoreSupport/ChromeClientWinCE.h +++ b/Source/WebKit/wince/WebCoreSupport/ChromeClientWinCE.h @@ -177,6 +177,7 @@ public: virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; } virtual void numWheelEventHandlersChanged(unsigned) { } + virtual void numTouchEventHandlersChanged(unsigned) { } private: WebView* m_webView; diff --git a/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.cpp b/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.cpp index 4cd3aac18..10c23731c 100644 --- a/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.cpp +++ b/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.cpp @@ -102,7 +102,7 @@ bool EditorClientWinCE::shouldChangeSelectedRange(Range*, Range*, EAffinity, boo return true; } -bool EditorClientWinCE::shouldApplyStyle(WebCore::CSSStyleDeclaration*, WebCore::Range*) +bool EditorClientWinCE::shouldApplyStyle(WebCore::StylePropertySet*, WebCore::Range*) { notImplemented(); return true; diff --git a/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.h b/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.h index c29524e1a..fc9ce023f 100644 --- a/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.h +++ b/Source/WebKit/wince/WebCoreSupport/EditorClientWinCE.h @@ -55,7 +55,7 @@ public: virtual bool shouldInsertText(const WTF::String&, WebCore::Range*, WebCore::EditorInsertAction); virtual bool shouldChangeSelectedRange(WebCore::Range*, WebCore::Range*, WebCore::EAffinity, bool); - virtual bool shouldApplyStyle(WebCore::CSSStyleDeclaration*, WebCore::Range*); + virtual bool shouldApplyStyle(WebCore::StylePropertySet*, WebCore::Range*); virtual bool shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*); virtual void didBeginEditing(); @@ -101,7 +101,7 @@ public: virtual void getGuessesForWord(const WTF::String& word, const WTF::String& context, WTF::Vector<WTF::String>& guesses); virtual void willSetInputMethodState(); virtual void setInputMethodState(bool); - virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&) {} + virtual void requestCheckingOfString(WebCore::SpellChecker*, const WebCore::TextCheckingRequest&) { } virtual WebCore::TextCheckerClient* textChecker() { return this; } private: diff --git a/Source/WebKit/wince/WebCoreSupport/PlatformStrategiesWinCE.cpp b/Source/WebKit/wince/WebCoreSupport/PlatformStrategiesWinCE.cpp index 3836cbd6a..3f8c907c7 100644 --- a/Source/WebKit/wince/WebCoreSupport/PlatformStrategiesWinCE.cpp +++ b/Source/WebKit/wince/WebCoreSupport/PlatformStrategiesWinCE.cpp @@ -58,6 +58,11 @@ VisitedLinkStrategy* PlatformStrategiesWinCE::createVisitedLinkStrategy() return this; } +PasteboardStrategy* PlatformStrategiesWinCE::createPasteboardStrategy() +{ + return 0; +} + void PlatformStrategiesWinCE::notifyCookiesChanged() { } diff --git a/Source/WebKit/wince/WebCoreSupport/PlatformStrategiesWinCE.h b/Source/WebKit/wince/WebCoreSupport/PlatformStrategiesWinCE.h index 92d37dc65..344635690 100644 --- a/Source/WebKit/wince/WebCoreSupport/PlatformStrategiesWinCE.h +++ b/Source/WebKit/wince/WebCoreSupport/PlatformStrategiesWinCE.h @@ -26,7 +26,6 @@ #define PlatformStrategiesWinCE_h #include "CookiesStrategy.h" -#include "LocalizationStrategy.h" #include "PlatformStrategies.h" #include "PluginStrategy.h" #include "VisitedLinkStrategy.h" @@ -42,6 +41,7 @@ private: virtual WebCore::CookiesStrategy* createCookiesStrategy(); virtual WebCore::PluginStrategy* createPluginStrategy(); virtual WebCore::VisitedLinkStrategy* createVisitedLinkStrategy(); + virtual WebCore::PasteboardStrategy* createPasteboardStrategy(); // WebCore::CookiesStrategy virtual void notifyCookiesChanged(); diff --git a/Source/WebKit/wx/ChangeLog b/Source/WebKit/wx/ChangeLog index b45b35005..0c6021eab 100644 --- a/Source/WebKit/wx/ChangeLog +++ b/Source/WebKit/wx/ChangeLog @@ -1,3 +1,47 @@ +2012-02-24 Shinya Kawanaka <shinyak@chromium.org> + + SpellCheckRequest needs to know the context where the spellcheck happened. + https://bugs.webkit.org/show_bug.cgi?id=79320 + + Reviewed by Hajime Morita. + + * WebKitSupport/EditorClientWx.h: + (WebCore::EditorClientWx::requestCheckingOfString): + +2012-02-21 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebKitSupport/EditorClientWx.cpp: + (WebCore::EditorClientWx::shouldApplyStyle): + * WebKitSupport/EditorClientWx.h: + (EditorClientWx): + +2012-02-22 Ryosuke Niwa <rniwa@webkit.org> + + Remove the remaining uses of CSSStyleDeclaration in Editor + https://bugs.webkit.org/show_bug.cgi?id=78939 + + Reviewed by Enrica Casucci. + + * WebKitSupport/EditorClientWx.cpp: + (WebCore::EditorClientWx::shouldApplyStyle): + * WebKitSupport/EditorClientWx.h: + (EditorClientWx): + +2012-02-15 Sadrul Habib Chowdhury <sadrul@chromium.org> + + Notify ChromeClient when touch-event handlers are installed/removed. + https://bugs.webkit.org/show_bug.cgi?id=77440 + + Reviewed by Darin Fisher and Ryosuke Niwa. + + * WebKitSupport/ChromeClientWx.h: + (WebCore::ChromeClientWx::numTouchEventHandlersChanged): + 2012-01-30 Kevin Ollivier <kevino@theolliviers.com> [wx] Unreviewed. Build fix, add JavaScriptCore/runtime diff --git a/Source/WebKit/wx/WebKitSupport/ChromeClientWx.h b/Source/WebKit/wx/WebKitSupport/ChromeClientWx.h index dcd164f34..2b6cdef61 100644 --- a/Source/WebKit/wx/WebKitSupport/ChromeClientWx.h +++ b/Source/WebKit/wx/WebKitSupport/ChromeClientWx.h @@ -151,6 +151,7 @@ public: virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const { return true; } virtual void numWheelEventHandlersChanged(unsigned) { } + virtual void numTouchEventHandlersChanged(unsigned) { } virtual bool hasOpenedPopup() const; diff --git a/Source/WebKit/wx/WebKitSupport/EditorClientWx.cpp b/Source/WebKit/wx/WebKitSupport/EditorClientWx.cpp index 81d54f813..f2f9ca775 100644 --- a/Source/WebKit/wx/WebKitSupport/EditorClientWx.cpp +++ b/Source/WebKit/wx/WebKitSupport/EditorClientWx.cpp @@ -223,7 +223,7 @@ bool EditorClientWx::shouldInsertText(const String&, Range*, return true; } -bool EditorClientWx::shouldApplyStyle(CSSStyleDeclaration*, +bool EditorClientWx::shouldApplyStyle(StylePropertySet*, Range*) { notImplemented(); diff --git a/Source/WebKit/wx/WebKitSupport/EditorClientWx.h b/Source/WebKit/wx/WebKitSupport/EditorClientWx.h index d1403d17f..ece15fa87 100644 --- a/Source/WebKit/wx/WebKitSupport/EditorClientWx.h +++ b/Source/WebKit/wx/WebKitSupport/EditorClientWx.h @@ -64,7 +64,7 @@ public: EditorInsertAction); virtual bool shouldInsertText(const String&, Range*, EditorInsertAction); - virtual bool shouldApplyStyle(CSSStyleDeclaration*, + virtual bool shouldApplyStyle(StylePropertySet*, Range*); virtual bool shouldMoveRangeAfterDelete(Range*, Range*); virtual bool shouldChangeSelectedRange(Range* fromRange, Range* toRange, @@ -114,7 +114,7 @@ public: virtual void willSetInputMethodState(); virtual void setInputMethodState(bool enabled); - virtual void requestCheckingOfString(WebCore::SpellChecker*, int, WebCore::TextCheckingTypeMask, const WTF::String&) {} + virtual void requestCheckingOfString(WebCore::SpellChecker*, const WebCore::TextCheckingRequest&) { } virtual TextCheckerClient* textChecker() { return this; } private: |