diff options
| author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
|---|---|---|
| committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
| commit | 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch) | |
| tree | 988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebKit/blackberry/Api/WebPage.cpp | |
| parent | dd91e772430dc294e3bf478c119ef8d43c0a3358 (diff) | |
| download | qtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz | |
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/WebKit/blackberry/Api/WebPage.cpp')
| -rw-r--r-- | Source/WebKit/blackberry/Api/WebPage.cpp | 882 |
1 files changed, 680 insertions, 202 deletions
diff --git a/Source/WebKit/blackberry/Api/WebPage.cpp b/Source/WebKit/blackberry/Api/WebPage.cpp index ad433607e..21e906a3b 100644 --- a/Source/WebKit/blackberry/Api/WebPage.cpp +++ b/Source/WebKit/blackberry/Api/WebPage.cpp @@ -25,12 +25,17 @@ #include "BackingStoreClient.h" #include "BackingStoreCompositingSurface.h" #include "BackingStore_p.h" +#if ENABLE(BATTERY_STATUS) +#include "BatteryClientBlackBerry.h" +#endif #include "CString.h" #include "CachedImage.h" #include "Chrome.h" #include "ChromeClientBlackBerry.h" #include "ContextMenuClientBlackBerry.h" #include "CookieManager.h" +#include "CredentialManager.h" +#include "CredentialTransformData.h" #include "DOMSupport.h" #include "Database.h" #include "DatabaseSync.h" @@ -46,17 +51,16 @@ #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 "HTMLMediaElement.h" #include "HTMLNames.h" #include "HTMLParserIdioms.h" #include "HTTPParsers.h" @@ -72,7 +76,7 @@ #include "LayerWebKitThread.h" #include "NetworkManager.h" #include "NodeRenderStyle.h" -#if ENABLE(NOTIFICATIONS) +#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) #include "NotificationPresenterImpl.h" #endif #include "Page.h" @@ -82,6 +86,8 @@ #include "PlatformWheelEvent.h" #include "PluginDatabase.h" #include "PluginView.h" +#include "RenderLayerBacking.h" +#include "RenderLayerCompositor.h" #include "RenderText.h" #include "RenderThemeBlackBerry.h" #include "RenderTreeAsText.h" @@ -99,12 +105,17 @@ #include "ThreadCheck.h" #include "TouchEventHandler.h" #include "TransformationMatrix.h" +#if ENABLE(VIBRATION) +#include "VibrationClientBlackBerry.h" +#endif #include "VisiblePosition.h" #if ENABLE(WEBDOM) #include "WebDOMDocument.h" #endif +#include "WebKitVersion.h" #include "WebPageClient.h" #include "WebSocket.h" +#include "WebViewportArguments.h" #include "npapi.h" #include "runtime_root.h" @@ -120,9 +131,10 @@ #if USE(ACCELERATED_COMPOSITING) #include "FrameLayers.h" -#include "WebPageCompositor.h" +#include "WebPageCompositor_p.h" #endif +#include <BlackBerryPlatformDeviceInfo.h> #include <BlackBerryPlatformExecutableMessage.h> #include <BlackBerryPlatformITPolicy.h> #include <BlackBerryPlatformKeyboardEvent.h> @@ -140,14 +152,19 @@ #include <memalloc.h> #endif -#if ENABLE(SKIA_GPU_CANVAS) -#include "BlackBerryPlatformGraphics.h" +#if ENABLE(ACCELERATED_2D_CANVAS) +#include "SharedGraphicsContext3D.h" #include "GrContext.h" #endif +#if ENABLE(REQUEST_ANIMATION_FRAME) +#include "PlatformScreen.h" +#endif + #define DEBUG_BLOCK_ZOOM 0 #define DEBUG_TOUCH_EVENTS 0 #define DEBUG_WEBPAGE_LOAD 0 +#define DEBUG_AC_COMMIT 0 using namespace std; using namespace WebCore; @@ -192,16 +209,16 @@ static KURL parseUrl(const String& url) } // Helper functions to convert to and from WebCore types. -static inline MouseEventType toWebCoreMouseEventType(const Platform::MouseEvent::Type type) +static inline WebCore::PlatformEvent::Type toWebCoreMouseEventType(const BlackBerry::Platform::MouseEvent::Type type) { switch (type) { - case Platform::MouseEvent::MouseButtonDown: - return MouseEventPressed; + case BlackBerry::Platform::MouseEvent::MouseButtonDown: + return WebCore::PlatformEvent::MousePressed; case Platform::MouseEvent::MouseButtonUp: - return MouseEventReleased; + return WebCore::PlatformEvent::MouseReleased; case Platform::MouseEvent::MouseMove: default: - return MouseEventMoved; + return WebCore::PlatformEvent::MouseMoved; } } @@ -262,6 +279,31 @@ static inline WebPage::BackForwardId backForwardIdFromHistoryItem(HistoryItem* i return reinterpret_cast<WebPage::BackForwardId>(item); } +void WebPage::setUserViewportArguments(const WebViewportArguments& viewportArguments) +{ + d->m_userViewportArguments = *(viewportArguments.d); +} + +void WebPage::resetUserViewportArguments() +{ + d->m_userViewportArguments = ViewportArguments(); +} + +template <bool WebPagePrivate::* isActive> +class DeferredTask: public WebPagePrivate::DeferredTaskBase { +public: + static void finishOrCancel(WebPagePrivate* webPagePrivate) + { + webPagePrivate->*isActive = false; + } +protected: + DeferredTask(WebPagePrivate* webPagePrivate) + : DeferredTaskBase(webPagePrivate, isActive) + { + } + typedef DeferredTask<isActive> DeferredTaskType; +}; + WebPagePrivate::WebPagePrivate(WebPage* webPage, WebPageClient* client, const IntRect& rect) : m_webPage(webPage) , m_client(client) @@ -270,6 +312,7 @@ WebPagePrivate::WebPagePrivate(WebPage* webPage, WebPageClient* client, const In , m_currentContextNode(0) , m_webSettings(0) // Initialized by init. , m_visible(false) + , m_activationState(ActivationActive) , m_shouldResetTilesWhenShown(false) , m_userScalable(true) , m_userPerformedManualZoom(false) @@ -317,10 +360,8 @@ WebPagePrivate::WebPagePrivate(WebPage* webPage, WebPageClient* client, const In , 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) @@ -330,7 +371,14 @@ WebPagePrivate::WebPagePrivate(WebPage* webPage, WebPageClient* client, const In , m_fullscreenVideoNode(0) , m_hasInRegionScrollableAreas(false) , m_updateDelegatedOverlaysDispatched(false) + , m_deferredTasksTimer(this, &WebPagePrivate::deferredTasksTimerFired) { + static bool isInitialized = false; + if (!isInitialized) { + isInitialized = true; + BlackBerry::Platform::DeviceInfo::instance(); + defaultUserAgent(); + } } WebPage::WebPage(WebPageClient* client, const WebString& pageGroupName, const Platform::IntRect& rect) @@ -380,7 +428,7 @@ WebPagePrivate::~WebPagePrivate() WebPage::~WebPage() { - delete d; + deleteGuardedObject(d); d = 0; } @@ -415,36 +463,36 @@ void WebPagePrivate::init(const WebString& pageGroupName) pageClients.dragClient = dragClient; pageClients.inspectorClient = inspectorClient; -#if ENABLE(CLIENT_BASED_GEOLOCATION) - // Note the object will be destroyed when the page is destroyed. + m_page = new Page(pageClients); #if ENABLE_DRT - if (getenv("drtRun")) - pageClients.geolocationClient = new GeolocationClientMock(); - else -#endif - pageClients.geolocationClient = m_geolocationClient = new GeolocationControllerClientBlackBerry(this); + if (getenv("drtRun")) { + // In case running in DumpRenderTree mode set the controller to mock provider. + GeolocationClientMock* mock = new GeolocationClientMock(); + WebCore::provideGeolocationTo(m_page, mock); + mock->setController(WebCore::GeolocationController::from(m_page)); + } else #else - pageClients.geolocationClient = m_geolocationClient; + WebCore::provideGeolocationTo(m_page, new GeolocationControllerClientBlackBerry(this)); +#endif + WebCore::provideDeviceOrientationTo(m_page, new DeviceOrientationClientBlackBerry(this)); + WebCore::provideDeviceMotionTo(m_page, new DeviceMotionClientBlackBerry(this)); +#if ENABLE(VIBRATION) + WebCore::provideVibrationTo(m_page, new VibrationClientBlackBerry()); #endif - pageClients.deviceMotionClient = new DeviceMotionClientBlackBerry(this); - pageClients.deviceOrientationClient = new DeviceOrientationClientBlackBerry(this); - m_page = new Page(pageClients); - -#if ENABLE(NOTIFICATIONS) - WebCore::provideNotification(m_page, NotificationPresenterImpl::instance()); +#if ENABLE(BATTERY_STATUS) + WebCore::provideBatteryTo(m_page, new WebCore::BatteryClientBlackBerry); #endif -#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()); +#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) + WebCore::provideNotification(m_page, NotificationPresenterImpl::instance()); #endif m_page->setCustomHTMLTokenizerChunkSize(256); m_page->setCustomHTMLTokenizerTimeDelay(0.3); m_webSettings = WebSettings::createFromStandardSettings(); + m_webSettings->setUserAgentString(defaultUserAgent()); // 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 @@ -463,7 +511,7 @@ void WebPagePrivate::init(const WebString& pageGroupName) Platform::Settings* settings = Platform::Settings::get(); m_page->settings()->setWebGLEnabled(settings && settings->isWebGLSupported()); #endif -#if ENABLE(SKIA_GPU_CANVAS) +#if ENABLE(ACCELERATED_2D_CANVAS) m_page->settings()->setCanvasUsesAcceleratedDrawing(true); m_page->settings()->setAccelerated2dCanvasEnabled(true); #endif @@ -485,11 +533,34 @@ void WebPagePrivate::init(const WebString& pageGroupName) blockClickRadius = int(roundf(0.35 * Platform::Graphics::Screen::primaryScreen()->pixelsPerInch(0).width())); // The clicked rectangle area should be a fixed unit of measurement. m_page->settings()->setDelegateSelectionPaint(true); + +#if ENABLE(REQUEST_ANIMATION_FRAME) + m_page->windowScreenDidChange((PlatformDisplayID)0); +#endif + +#if ENABLE(WEB_TIMING) + m_page->settings()->setMemoryInfoEnabled(true); +#endif } -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) +class DeferredTaskLoadManualScript: public DeferredTask<&WebPagePrivate::m_wouldLoadManualScript> { +public: + explicit DeferredTaskLoadManualScript(WebPagePrivate* webPagePrivate, const KURL& url) + : DeferredTaskType(webPagePrivate) + { + webPagePrivate->m_cachedManualScript = url; + } +private: + virtual void performInternal(WebPagePrivate* webPagePrivate) + { + webPagePrivate->m_mainFrame->script()->executeIfJavaScriptURL(webPagePrivate->m_cachedManualScript, DoNotReplaceDocumentIfJavaScriptURL); + } +}; + +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, const char* suggestedSaveName) { stopCurrentLoad(); + DeferredTaskLoadManualScript::finishOrCancel(this); String urlString(url); if (urlString.startsWith("vs:", false)) { @@ -501,10 +572,9 @@ void WebPagePrivate::load(const char* url, const char* networkToken, const char* 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 + if (m_page->defersLoading()) + m_deferredTasks.append(adoptPtr(new DeferredTaskLoadManualScript(this, kurl))); + else m_mainFrame->script()->executeIfJavaScriptURL(kurl, DoNotReplaceDocumentIfJavaScriptURL); return; } @@ -512,7 +582,7 @@ void WebPagePrivate::load(const char* url, const char* networkToken, const char* if (isInitial) NetworkManager::instance()->setInitialURL(kurl); - ResourceRequest request(kurl, "" /* referrer */); + ResourceRequest request(kurl); request.setToken(networkToken); if (isInitial || mustHandleInternally) request.setMustHandleInternally(true); @@ -530,6 +600,8 @@ void WebPagePrivate::load(const char* url, const char* networkToken, const char* if (forceDownload) request.setForceDownload(true); + request.setSuggestedSaveName(suggestedSaveName); + m_mainFrame->loader()->load(request, "" /* name */, false); } @@ -556,7 +628,7 @@ void WebPage::loadFile(const char* path, const char* overrideContentType) 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, ""); + d->load(request.getUrlRef().c_str(), 0, "GET", Platform::NetworkRequest::UseProtocolCachePolicy, 0, 0, 0, 0, false, false, true, "", request.getSuggestedSaveName().c_str()); } void WebPagePrivate::loadString(const char* string, const char* baseURL, const char* contentType, const char* failingURL) @@ -711,8 +783,7 @@ void WebPagePrivate::stopCurrentLoad() 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()); + DeferredTaskLoadManualScript::finishOrCancel(this); } void WebPage::stopLoading() @@ -781,23 +852,19 @@ void WebPagePrivate::setLoadState(LoadState state) { unscheduleZoomAboutPoint(); -#if ENABLE(SKIA_GPU_CANVAS) +#if ENABLE(ACCELERATED_2D_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); + SharedGraphicsContext3D::get()->makeContextCurrent(); 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()); - } + if (isAcceleratedCompositingActive() && !compositorDrawsRootLayer()) + syncDestroyCompositorOnCompositingThread(); #endif m_previousContentsSize = IntSize(); m_backingStore->d->resetRenderQueue(); @@ -817,6 +884,12 @@ void WebPagePrivate::setLoadState(LoadState state) // Check if we have already process the meta viewport tag, this only happens on history navigation if (!m_didRestoreFromPageCache) { m_viewportArguments = ViewportArguments(); + + // At the moment we commit a new load, set the viewport arguments + // to any fallback values. If there is a meta viewport in the + // content it will overwrite the fallback arguments soon. + dispatchViewportPropertiesDidChange(m_userViewportArguments); + m_userScalable = m_webSettings->isUserScalable(); resetScales(); } else { @@ -845,6 +918,9 @@ void WebPagePrivate::setLoadState(LoadState state) toggleTextReflowIfEnabledForBlockZoomOnly(); #endif + // Notify InputHandler of state change. + m_inputHandler->enableInputMode(false); + // 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. @@ -1175,14 +1251,32 @@ bool WebPagePrivate::shouldSendResizeEvent() void WebPagePrivate::willDeferLoading() { + m_deferredTasksTimer.stop(); m_client->willDeferLoading(); } void WebPagePrivate::didResumeLoading() { + if (!m_deferredTasks.isEmpty()) + m_deferredTasksTimer.startOneShot(0); m_client->didResumeLoading(); } +void WebPagePrivate::deferredTasksTimerFired(WebCore::Timer<WebPagePrivate>*) +{ + ASSERT(!m_deferredTasks.isEmpty()); + if (!m_deferredTasks.isEmpty()) + return; + + OwnPtr<DeferredTaskBase> task = m_deferredTasks[0].release(); + m_deferredTasks.remove(0); + + if (!m_deferredTasks.isEmpty()) + m_deferredTasksTimer.startOneShot(0); + + task->perform(this); +} + bool WebPagePrivate::scrollBy(int deltaX, int deltaY, bool scrollMainFrame) { IntSize delta(deltaX, deltaY); @@ -1547,6 +1641,11 @@ bool WebPage::isUserScalable() const return d->isUserScalable(); } +void WebPage::setUserScalable(bool userScalable) +{ + d->setUserScalable(userScalable); +} + double WebPage::currentScale() const { return d->currentScale(); @@ -1843,7 +1942,7 @@ bool WebPagePrivate::setViewMode(ViewMode mode) return true; // Needs re-layout! } -void WebPagePrivate::setCursor(PlatformCursorHandle handle) +void WebPagePrivate::setCursor(PlatformCursor handle) { if (m_currentCursor.type() != handle.type()) { m_currentCursor = handle; @@ -1930,6 +2029,10 @@ void WebPagePrivate::didPluginEnterFullScreen(PluginView* plugin, const char* wi { m_fullScreenPluginView = plugin; m_client->didPluginEnterFullScreen(); + + if (!m_client->window()) + return; + Platform::Graphics::Window::setTransparencyDiscardFilter(windowUniquePrefix); m_client->window()->setSensitivityFullscreenOverride(true); } @@ -1938,6 +2041,10 @@ void WebPagePrivate::didPluginExitFullScreen(PluginView* plugin, const char* win { m_fullScreenPluginView = 0; m_client->didPluginExitFullScreen(); + + if (!m_client->window()) + return; + Platform::Graphics::Window::setTransparencyDiscardFilter(0); m_client->window()->setSensitivityFullscreenOverride(false); } @@ -1987,14 +2094,41 @@ bool WebPagePrivate::isActive() const return m_client->isActive(); } +Credential WebPagePrivate::authenticationChallenge(const KURL& url, const ProtectionSpace& protectionSpace) +{ + WebString username; + WebString password; + +#if ENABLE(BLACKBERRY_CREDENTIAL_PERSIST) + if (!m_webSettings->isPrivateBrowsingEnabled()) + credentialManager().autofillAuthenticationChallenge(protectionSpace, username, password); +#endif + + m_client->authenticationChallenge(protectionSpace.realm().characters(), protectionSpace.realm().length(), username, password); + +#if ENABLE(BLACKBERRY_CREDENTIAL_PERSIST) + Credential inputCredential(username, password, CredentialPersistencePermanent); + if (!m_webSettings->isPrivateBrowsingEnabled()) + credentialManager().saveCredentialIfConfirmed(this, CredentialTransformData(url, protectionSpace, inputCredential)); +#else + Credential inputCredential(username, password, CredentialPersistenceNone); +#endif + return inputCredential; +} + +PageClientBlackBerry::SaveCredentialType WebPagePrivate::notifyShouldSaveCredential(bool isNew) +{ + return static_cast<PageClientBlackBerry::SaveCredentialType>(m_client->notifyShouldSaveCredential(isNew)); +} + bool WebPagePrivate::useFixedLayout() const { return true; } -ActiveNodeContext WebPagePrivate::activeNodeContext(TargetDetectionStrategy strategy) +Platform::WebContext WebPagePrivate::webContext(TargetDetectionStrategy strategy) { - ActiveNodeContext context; + Platform::WebContext context; RefPtr<Node> node = contextNode(strategy); m_currentContextNode = node; @@ -2007,16 +2141,16 @@ ActiveNodeContext WebPagePrivate::activeNodeContext(TargetDetectionStrategy stra if (Node* linkNode = node->enclosingLinkEventParentOrSelf()) { KURL href; if (linkNode->isLink() && linkNode->hasAttributes()) { - if (Attribute* attribute = linkNode->attributes()->getAttributeItem(HTMLNames::hrefAttr)) + if (Attribute* attribute = static_cast<Element*>(linkNode)->getAttributeItem(HTMLNames::hrefAttr)) href = linkNode->document()->completeURL(stripLeadingAndTrailingHTMLSpaces(attribute->value())); } String pattern = findPatternStringForUrl(href); if (!pattern.isEmpty()) - context.setPattern(pattern); + context.setPattern(pattern.utf8().data()); if (!href.string().isEmpty()) { - context.setUrl(href.string()); + context.setUrl(href.string().utf8().data()); // Links are non-selectable by default, but selection should be allowed // providing the page is selectable, use the parent to determine it. @@ -2026,58 +2160,75 @@ ActiveNodeContext WebPagePrivate::activeNodeContext(TargetDetectionStrategy stra } if (!nodeAllowSelectionOverride && !node->canStartSelection()) - context.resetFlag(ActiveNodeContext::IsSelectable); + context.resetFlag(Platform::WebContext::IsSelectable); if (node->isHTMLElement()) { HTMLImageElement* imageElement = 0; + HTMLMediaElement* mediaElement = 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 (static_cast<HTMLElement*>(node.get())->isMediaElement()) + mediaElement = static_cast<HTMLMediaElement*>(node.get()); + if (imageElement && imageElement->renderer()) { + context.setFlag(Platform::WebContext::IsImage); // 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()); + context.setSrc(node->document()->completeURL(url).string().utf8().data()); } } String alt = imageElement->altText(); if (!alt.isNull()) - context.setImageAlt(alt); + context.setAlt(alt.utf8().data()); + } + + if (mediaElement) { + if (mediaElement->hasAudio()) + context.setFlag(Platform::WebContext::IsAudio); + if (mediaElement->hasVideo()) + context.setFlag(Platform::WebContext::IsVideo); + + String src = stripLeadingAndTrailingHTMLSpaces(mediaElement->getAttribute(HTMLNames::srcAttr).string()); + context.setSrc(node->document()->completeURL(src).string().utf8().data()); } } if (node->isTextNode()) { Text* curText = static_cast<Text*>(node.get()); if (!curText->wholeText().isEmpty()) - context.setText(curText->wholeText()); + context.setText(curText->wholeText().utf8().data()); } if (node->isElementNode()) { Element* element = static_cast<Element*>(node->shadowAncestorNode()); if (DOMSupport::isTextBasedContentEditableElement(element)) { - context.setFlag(ActiveNodeContext::IsInput); + context.setFlag(Platform::WebContext::IsInput); if (element->hasTagName(HTMLNames::inputTag)) - context.setFlag(ActiveNodeContext::IsSingleLine); + context.setFlag(Platform::WebContext::IsSingleLine); if (DOMSupport::isPasswordElement(element)) - context.setFlag(ActiveNodeContext::IsPassword); + context.setFlag(Platform::WebContext::IsPassword); String elementText(DOMSupport::inputElementText(element)); if (!elementText.stripWhiteSpace().isEmpty()) - context.setText(elementText); + context.setText(elementText.utf8().data()); } } if (node->isFocusable()) - context.setFlag(ActiveNodeContext::IsFocusable); + context.setFlag(Platform::WebContext::IsFocusable); return context; } -ActiveNodeContext WebPage::activeNodeContext(TargetDetectionStrategy strategy) const +Platform::WebContext WebPage::webContext(TargetDetectionStrategy strategy) const { - return d->activeNodeContext(strategy); + return d->webContext(strategy); } void WebPagePrivate::updateCursor() @@ -2090,7 +2241,7 @@ void WebPagePrivate::updateCursor() 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); + BlackBerry::Platform::MouseEvent event(buttonMask, buttonMask, mapToTransformed(m_lastMouseEvent.position()), mapToTransformed(m_lastMouseEvent.globalPosition()), 0, 0); m_webPage->mouseEvent(event); } @@ -2347,6 +2498,8 @@ void WebPagePrivate::assignFocus(Platform::FocusDirection direction) void WebPage::assignFocus(Platform::FocusDirection direction) { + if (d->m_page->defersLoading()) + return; d->assignFocus(direction); } @@ -2398,7 +2551,7 @@ PassRefPtr<Node> WebPagePrivate::contextNode(TargetDetectionStrategy strategy) if (isTouching) contentPos = lastFatFingersResult.adjustedPosition(); else - contentPos = mapFromViewportToContents(m_lastMouseEvent.pos()); + contentPos = mapFromViewportToContents(m_lastMouseEvent.position()); if (strategy == RectBased) { FatFingersResult result = FatFingers(this, lastFatFingersResult.adjustedPosition(), FatFingers::Text).findBestPoint(); @@ -2509,6 +2662,17 @@ Node* WebPagePrivate::adjustedBlockZoomNodeForZoomLimits(Node* node) acceptableNodeSize = newScaleForBlockZoomRect(rectForNode(node), 1.0, 0) < maxBlockZoomScale(); } + // Don't use a node if it is too close to the size of the actual contents. + if (initialNode != node) { + IntRect nodeRect = rectForNode(node); + nodeRect = adjustRectOffsetForFrameOffset(nodeRect, node); + nodeRect.intersect(IntRect(IntPoint::zero(), contentsSize())); + int nodeArea = nodeRect.width() * nodeRect.height(); + int pageArea = contentsSize().width() * contentsSize().height(); + if (static_cast<double>(pageArea - nodeArea) / pageArea < minimumExpandingRatio) + return initialNode; + } + return node; } @@ -2645,7 +2809,7 @@ IntRect WebPagePrivate::blockZoomRectForNode(Node* node) int originalArea = originalRect.width() * originalRect.height(); int pageArea = contentsSize().width() * contentsSize().height(); - double blockToPageRatio = static_cast<double>(1 - originalArea / pageArea); + double blockToPageRatio = static_cast<double>(pageArea - originalArea) / pageArea; double blockExpansionRatio = 5.0 * blockToPageRatio * blockToPageRatio; if (!tnode->hasTagName(HTMLNames::imgTag) && !tnode->hasTagName(HTMLNames::inputTag) && !tnode->hasTagName(HTMLNames::textareaTag)) { @@ -2654,7 +2818,7 @@ IntRect WebPagePrivate::blockZoomRectForNode(Node* node) 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) + if (static_cast<double>(pageArea - tempBlockArea) / pageArea < minimumExpandingRatio) break; if (tRect.isEmpty()) continue; // No renderer. @@ -2662,7 +2826,7 @@ IntRect WebPagePrivate::blockZoomRectForNode(Node* node) 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) + if (static_cast<double>(actualSize.width() - tRect.width()) / actualSize.width() < minimumExpandingRatio) break; if (tempBlockArea < blockExpansionRatio * originalArea) { blockRect = tRect; @@ -2825,7 +2989,7 @@ void WebPage::destroy() if (loader) loader->detachFromParent(); - delete this; + deleteGuardedObject(this); } WebPageClient* WebPage::client() const @@ -2879,12 +3043,50 @@ bool WebPage::isVisible() const return d->m_visible; } +#if ENABLE(PAGE_VISIBILITY_API) +class DeferredTaskSetPageVisibilityState: public DeferredTask<&WebPagePrivate::m_wouldSetPageVisibilityState> { +public: + explicit DeferredTaskSetPageVisibilityState(WebPagePrivate* webPagePrivate) + : DeferredTaskType(webPagePrivate) + { + } +private: + virtual void performInternal(WebPagePrivate* webPagePrivate) + { + webPagePrivate->setPageVisibilityState(); + } +}; + +void WebPagePrivate::setPageVisibilityState() +{ + if (m_page->defersLoading()) + m_deferredTasks.append(adoptPtr(new DeferredTaskSetPageVisibilityState(this))); + else { + DeferredTaskSetPageVisibilityState::finishOrCancel(this); + + static bool s_initialVisibilityState = true; + + m_page->setVisibilityState(m_visible && m_activationState == ActivationActive ? PageVisibilityStateVisible : PageVisibilityStateHidden, s_initialVisibilityState); + s_initialVisibilityState = false; + } +} +#endif + +void WebPagePrivate::setVisible(bool visible) +{ + m_visible = visible; + +#if ENABLE(PAGE_VISIBILITY_API) + setPageVisibilityState(); +#endif +} + void WebPage::setVisible(bool visible) { if (d->m_visible == visible) return; - d->m_visible = visible; + d->setVisible(visible); if (!visible) { d->suspendBackingStore(); @@ -2903,6 +3105,7 @@ void WebPage::setVisible(bool visible) // And release layer resources can reduce memory consumption. d->suspendRootLayerCommit(); #endif + return; } @@ -2971,6 +3174,8 @@ bool WebPage::setBatchEditingActive(bool active) bool WebPage::setInputSelection(unsigned start, unsigned end) { + if (d->m_page->defersLoading()) + return false; return d->m_inputHandler->setSelection(start, end); } @@ -2979,23 +3184,101 @@ int WebPage::inputCaretPosition() const return d->m_inputHandler->caretPosition(); } -void WebPage::popupListClosed(int size, bool* selecteds) +class DeferredTaskPopupListSelectMultiple: public DeferredTask<&WebPagePrivate::m_wouldPopupListSelectMultiple> { +public: + DeferredTaskPopupListSelectMultiple(WebPagePrivate* webPagePrivate, int size, const bool* selecteds) + : DeferredTaskType(webPagePrivate) + { + webPagePrivate->m_cachedPopupListSelecteds.append(selecteds, size); + } +private: + virtual void performInternal(WebPagePrivate* webPagePrivate) + { + webPagePrivate->m_webPage->popupListClosed(webPagePrivate->m_cachedPopupListSelecteds.size(), webPagePrivate->m_cachedPopupListSelecteds.data()); + } +}; + +class DeferredTaskPopupListSelectSingle: public DeferredTask<&WebPagePrivate::m_wouldPopupListSelectSingle> { +public: + explicit DeferredTaskPopupListSelectSingle(WebPagePrivate* webPagePrivate, int index) + : DeferredTaskType(webPagePrivate) + { + webPagePrivate->m_cachedPopupListSelectedIndex = index; + } +private: + virtual void performInternal(WebPagePrivate* webPagePrivate) + { + webPagePrivate->m_webPage->popupListClosed(webPagePrivate->m_cachedPopupListSelectedIndex); + } +}; + +void WebPage::popupListClosed(int size, const bool* selecteds) { + DeferredTaskPopupListSelectSingle::finishOrCancel(d); + if (d->m_page->defersLoading()) { + d->m_deferredTasks.append(adoptPtr(new DeferredTaskPopupListSelectMultiple(d, size, selecteds))); + return; + } + DeferredTaskPopupListSelectMultiple::finishOrCancel(d); d->m_inputHandler->setPopupListIndexes(size, selecteds); } void WebPage::popupListClosed(int index) { + DeferredTaskPopupListSelectMultiple::finishOrCancel(d); + if (d->m_page->defersLoading()) { + d->m_deferredTasks.append(adoptPtr(new DeferredTaskPopupListSelectSingle(d, index))); + return; + } + DeferredTaskPopupListSelectSingle::finishOrCancel(d); d->m_inputHandler->setPopupListIndex(index); } +class DeferredTaskSetDateTimeInput: public DeferredTask<&WebPagePrivate::m_wouldSetDateTimeInput> { +public: + explicit DeferredTaskSetDateTimeInput(WebPagePrivate* webPagePrivate, WebString value) + : DeferredTaskType(webPagePrivate) + { + webPagePrivate->m_cachedDateTimeInput = value; + } +private: + virtual void performInternal(WebPagePrivate* webPagePrivate) + { + webPagePrivate->m_webPage->setDateTimeInput(webPagePrivate->m_cachedDateTimeInput); + } +}; + void WebPage::setDateTimeInput(const WebString& value) { + if (d->m_page->defersLoading()) { + d->m_deferredTasks.append(adoptPtr(new DeferredTaskSetDateTimeInput(d, value))); + return; + } + DeferredTaskSetDateTimeInput::finishOrCancel(d); d->m_inputHandler->setInputValue(String(value.impl())); } +class DeferredTaskSetColorInput: public DeferredTask<&WebPagePrivate::m_wouldSetColorInput> { +public: + explicit DeferredTaskSetColorInput(WebPagePrivate* webPagePrivate, WebString value) + : DeferredTaskType(webPagePrivate) + { + webPagePrivate->m_cachedColorInput = value; + } +private: + virtual void performInternal(WebPagePrivate* webPagePrivate) + { + webPagePrivate->m_webPage->setColorInput(webPagePrivate->m_cachedColorInput); + } +}; + void WebPage::setColorInput(const WebString& value) { + if (d->m_page->defersLoading()) { + d->m_deferredTasks.append(adoptPtr(new DeferredTaskSetColorInput(d, value))); + return; + } + DeferredTaskSetColorInput::finishOrCancel(d); d->m_inputHandler->setInputValue(String(value.impl())); } @@ -3012,7 +3295,7 @@ void WebPage::resetVirtualViewportOnCommitted(bool reset) IntSize WebPagePrivate::recomputeVirtualViewportFromViewportArguments() { - static ViewportArguments defaultViewportArguments; + static const ViewportArguments defaultViewportArguments; if (m_viewportArguments == defaultViewportArguments) return IntSize(); @@ -3021,9 +3304,11 @@ IntSize WebPagePrivate::recomputeVirtualViewportFromViewportArguments() int deviceHeight = Platform::Graphics::Screen::primaryScreen()->height(); FloatSize currentPPI = Platform::Graphics::Screen::primaryScreen()->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. + if (m_viewportArguments.targetDensityDpi == ViewportArguments::ValueAuto + && !Platform::DeviceInfo::instance()->isMobile()) { + // If the content provider hasn't specified a target dpi and we have a large + // screen we assume the content is fine and set the targetDensityDpi to our dpi. + // On smaller screen mobile devices we skip this and use WebCore dpi scaling. m_viewportArguments.targetDensityDpi = deviceDPI; } @@ -3098,6 +3383,15 @@ void WebPage::onInputLocaleChanged(bool isRTL) void WebPagePrivate::suspendBackingStore() { #if USE(ACCELERATED_COMPOSITING) + if (m_backingStore->d->isOpenGLCompositing()) { + // A visible web page's backing store can be suspended when another web + // page is taking over the backing store. + if (m_visible) + setCompositorDrawsRootLayer(true); + + return; + } + resetCompositingSurface(); #endif } @@ -3106,10 +3400,6 @@ 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() @@ -3117,6 +3407,12 @@ void WebPagePrivate::resumeBackingStore() // 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); + + // If we're OpenGL compositing, switching to accel comp drawing of the root layer + // is a good substitute for backingstore blitting. + if (m_backingStore->d->isOpenGLCompositing()) + setCompositorDrawsRootLayer(!m_backingStore->d->isActive()); + 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 */); @@ -3125,10 +3421,17 @@ void WebPagePrivate::resumeBackingStore() if (m_backingStore->d->renderVisibleContents() && !m_backingStore->d->isSuspended() && !directRendering) m_backingStore->d->blitVisibleContents(); } else { + if (m_backingStore->d->isOpenGLCompositing()) + setCompositorDrawsRootLayer(false); + // Rendering was disabled while we were hidden, so we need to update all tiles. m_backingStore->d->updateTiles(true /* updateVisible */, false /* immediate */); } +#if USE(ACCELERATED_COMPOSITING) + setNeedsOneShotDrawingSynchronization(); +#endif + setShouldResetTilesWhenShown(false); } @@ -3411,6 +3714,9 @@ bool WebPage::mouseEvent(const Platform::MouseEvent& mouseEvent, bool* wheelDelt if (!d->m_mainFrame->view()) return false; + if (d->m_page->defersLoading()) + return false; + PluginView* pluginView = d->m_fullScreenPluginView.get(); if (pluginView) return d->dispatchMouseEventToFullScreenPlugin(pluginView, mouseEvent); @@ -3494,10 +3800,10 @@ bool WebPagePrivate::handleMouseEvent(PlatformMouseEvent& mouseEvent) { EventHandler* eventHandler = m_mainFrame->eventHandler(); - if (mouseEvent.eventType() == MouseEventMoved) + if (mouseEvent.type() == WebCore::PlatformEvent::MouseMoved) return eventHandler->mouseMoved(mouseEvent); - if (mouseEvent.eventType() == MouseEventScroll) + if (mouseEvent.type() == WebCore::PlatformEvent::MouseScroll) return true; Node* node = 0; @@ -3509,11 +3815,12 @@ bool WebPagePrivate::handleMouseEvent(PlatformMouseEvent& mouseEvent) } if (!node) { - HitTestResult result = eventHandler->hitTestResultAtPoint(mapFromViewportToContents(mouseEvent.pos()), false /*allowShadowContent*/); + HitTestResult result = eventHandler->hitTestResultAtPoint(mapFromViewportToContents(mouseEvent.position()), false /*allowShadowContent*/); node = result.innerNode(); } - if (mouseEvent.eventType() == MouseEventPressed) { + if (mouseEvent.type() == WebCore::PlatformEvent::MousePressed) { + m_inputHandler->enableInputMode(); 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 @@ -3533,7 +3840,7 @@ bool WebPagePrivate::handleMouseEvent(PlatformMouseEvent& mouseEvent) } } else eventHandler->handleMousePressEvent(mouseEvent); - } else if (mouseEvent.eventType() == MouseEventReleased) { + } else if (mouseEvent.type() == WebCore::PlatformEvent::MouseReleased) { // 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. @@ -3586,13 +3893,16 @@ bool WebPage::touchEvent(const Platform::TouchEvent& event) #endif #if ENABLE(TOUCH_EVENTS) + if (!d->m_mainFrame) + return false; + + if (d->m_page->defersLoading()) + return false; + 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); @@ -3710,6 +4020,9 @@ bool WebPagePrivate::dispatchTouchEventToFullScreenPlugin(PluginView* plugin, co bool WebPage::touchPointAsMouseEvent(const Platform::TouchPoint& point) { + if (d->m_page->defersLoading()) + return false; + PluginView* pluginView = d->m_fullScreenPluginView.get(); if (pluginView) return d->dispatchTouchPointAsMouseEventToFullScreenPlugin(pluginView, point); @@ -3755,11 +4068,15 @@ bool WebPagePrivate::dispatchTouchPointAsMouseEventToFullScreenPlugin(PluginView void WebPage::touchEventCancel() { d->m_pluginMayOpenNewTab = false; + if (d->m_page->defersLoading()) + return; d->m_touchEventHandler->touchEventCancel(); } void WebPage::touchEventCancelAndClearFocusedNode() { + if (d->m_page->defersLoading()) + return; d->m_touchEventHandler->touchEventCancelAndClearFocusedNode(); } @@ -3978,6 +4295,9 @@ bool WebPage::keyEvent(const Platform::KeyboardEvent& keyboardEvent) if (!d->m_mainFrame->view()) return false; + if (d->m_page->defersLoading()) + return false; + ASSERT(d->m_page->focusController()); bool handled = d->m_inputHandler->handleKeyboardInput(keyboardEvent); @@ -3993,6 +4313,9 @@ bool WebPage::keyEvent(const Platform::KeyboardEvent& keyboardEvent) bool WebPage::deleteTextRelativeToCursor(unsigned int leftOffset, unsigned int rightOffset) { + if (d->m_page->defersLoading()) + return false; + return d->m_inputHandler->deleteTextRelativeToCursor(leftOffset, rightOffset); } @@ -4028,11 +4351,15 @@ int32_t WebPage::finishComposition() int32_t WebPage::setComposingText(spannable_string_t* spannableString, int32_t relativeCursorPosition) { + if (d->m_page->defersLoading()) + return -1; return d->m_inputHandler->setComposingText(spannableString, relativeCursorPosition); } int32_t WebPage::commitText(spannable_string_t* spannableString, int32_t relativeCursorPosition) { + if (d->m_page->defersLoading()) + return -1; return d->m_inputHandler->commitText(spannableString, relativeCursorPosition); } @@ -4041,8 +4368,26 @@ void WebPage::setSpellCheckingEnabled(bool enabled) static_cast<EditorClientBlackBerry*>(d->m_page->editorClient())->enableSpellChecking(enabled); } +class DeferredTaskSelectionCancelled: public DeferredTask<&WebPagePrivate::m_wouldCancelSelection> { +public: + explicit DeferredTaskSelectionCancelled(WebPagePrivate* webPagePrivate) + : DeferredTaskType(webPagePrivate) + { + } +private: + virtual void performInternal(WebPagePrivate* webPagePrivate) + { + webPagePrivate->m_webPage->selectionCancelled(); + } +}; + void WebPage::selectionCancelled() { + if (d->m_page->defersLoading()) { + d->m_deferredTasks.append(adoptPtr(new DeferredTaskSelectionCancelled(d))); + return; + } + DeferredTaskSelectionCancelled::finishOrCancel(d); d->m_selectionHandler->cancelSelection(); } @@ -4066,23 +4411,29 @@ WebString WebPage::selectedText() const WebString WebPage::cutSelectedText() { WebString selectedText = d->m_selectionHandler->selectedText(); - if (!selectedText.isEmpty()) + if (!d->m_page->defersLoading() && !selectedText.isEmpty()) d->m_inputHandler->deleteSelection(); return selectedText; } void WebPage::insertText(const WebString& string) { + if (d->m_page->defersLoading()) + return; d->m_inputHandler->insertText(string); } void WebPage::clearCurrentInputField() { + if (d->m_page->defersLoading()) + return; d->m_inputHandler->clearField(); } void WebPage::cut() { + if (d->m_page->defersLoading()) + return; d->m_inputHandler->cut(); } @@ -4093,11 +4444,15 @@ void WebPage::copy() void WebPage::paste() { + if (d->m_page->defersLoading()) + return; d->m_inputHandler->paste(); } void WebPage::setSelection(const Platform::IntPoint& startPoint, const Platform::IntPoint& endPoint) { + if (d->m_page->defersLoading()) + return; // 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 @@ -4112,6 +4467,8 @@ void WebPage::setSelection(const Platform::IntPoint& startPoint, const Platform: void WebPage::setCaretPosition(const Platform::IntPoint& position) { + if (d->m_page->defersLoading()) + return; // Handled by selection handler as it's point based. // Transform this events coordinates to webkit content coordinates. d->m_selectionHandler->setCaretPosition(d->mapFromTransformed(position)); @@ -4119,6 +4476,8 @@ void WebPage::setCaretPosition(const Platform::IntPoint& position) void WebPage::selectAtPoint(const Platform::IntPoint& location) { + if (d->m_page->defersLoading()) + return; // Transform this events coordinates to webkit content coordinates if it // is not the sentinel value. IntPoint selectionLocation = @@ -4343,7 +4702,7 @@ bool WebPage::blockZoom(int x, int y) 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); + double blockToPageRatio = static_cast<double>(pageArea - blockArea) / pageArea; if (blockToPageRatio < minimumExpandingRatio) { // Restore old adjust node because zoom was canceled. d->m_currentBlockZoomAdjustedNode = tempBlockZoomAdjustedNode; @@ -4552,8 +4911,27 @@ bool WebPage::zoomToOneOne() return d->zoomAboutPoint(scale, d->centerOfVisibleContentsRect()); } +class DeferredTaskSetFocused: public DeferredTask<&WebPagePrivate::m_wouldSetFocused> { +public: + explicit DeferredTaskSetFocused(WebPagePrivate* webPagePrivate, bool focused) + : DeferredTaskType(webPagePrivate) + { + webPagePrivate->m_cachedFocused = focused; + } +private: + virtual void performInternal(WebPagePrivate* webPagePrivate) + { + webPagePrivate->m_webPage->setFocused(webPagePrivate->m_cachedFocused); + } +}; + void WebPage::setFocused(bool focused) { + if (d->m_page->defersLoading()) { + d->m_deferredTasks.append(adoptPtr(new DeferredTaskSetFocused(d, focused))); + return; + } + DeferredTaskSetFocused::finishOrCancel(d); FocusController* focusController = d->m_page->focusController(); focusController->setActive(focused); if (focused) { @@ -4564,9 +4942,18 @@ void WebPage::setFocused(bool focused) focusController->setFocused(focused); } -bool WebPage::findNextString(const char* text, bool forward) +bool WebPage::findNextString(const char* text, bool forward, bool caseSensitive, bool wrap, bool highlightAllMatches) { - return d->m_inPageSearchManager->findNextString(String::fromUTF8(text), forward); + WebCore::FindOptions findOptions = WebCore::StartInSelection; + if (!forward) + findOptions |= WebCore::Backwards; + if (!caseSensitive) + findOptions |= WebCore::CaseInsensitive; + + // The WebCore::FindOptions::WrapAround boolean actually wraps the search + // within the current frame as opposed to the entire Document, so we have to + // provide our own wrapping code to wrap at the whole Document level. + return d->m_inPageSearchManager->findNextString(String::fromUTF8(text), findOptions, wrap, highlightAllMatches); } void WebPage::runLayoutTests() @@ -4771,8 +5158,24 @@ void WebPage::clearCookies() void WebPage::clearLocalStorage() { - BlackBerry::WebKit::clearLocalStorage(d->m_page->groupName()); - clearDatabase(d->m_page->groupName()); + if (PageGroup* group = d->m_page->groupPtr()) { + if (StorageNamespace* storage = group->localStorage()) + storage->clearAllOriginsForDeletion(); + } +} + +void WebPage::clearCredentials() +{ +#if ENABLE(BLACKBERRY_CREDENTIAL_PERSIST) + credentialManager().clearCredentials(); +#endif +} + +void WebPage::clearNeverRememberSites() +{ +#if ENABLE(BLACKBERRY_CREDENTIAL_PERSIST) + credentialManager().clearNeverRememberSites(); +#endif } void WebPage::clearCache() @@ -4943,6 +5346,15 @@ void WebPage::notifyDeviceIdleStateChange(bool enterIdle) (*it)->handleIdleEvent(enterIdle); } +void WebPagePrivate::notifyAppActivationStateChange(ActivationStateType activationState) +{ + m_activationState = activationState; + +#if ENABLE(PAGE_VISIBILITY_API) + setPageVisibilityState(); +#endif +} + void WebPage::notifyAppActivationStateChange(ActivationStateType activationState) { #if ENABLE(VIDEO) @@ -4960,11 +5372,10 @@ void WebPage::notifyAppActivationStateChange(ActivationStateType activationState 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; } } + + d->notifyAppActivationStateChange(activationState); } void WebPage::notifySwipeEvent() @@ -5043,10 +5454,41 @@ void WebPage::disablePasswordEcho() void WebPage::dispatchInspectorMessage(const std::string& message) { - String stringMessage(message.c_str(), message.length()); + String stringMessage = String::fromUTF8(message.data(), message.length()); d->m_page->inspectorController()->dispatchMessageFromFrontend(stringMessage); } +bool WebPagePrivate::compositorDrawsRootLayer() const +{ +#if USE(ACCELERATED_COMPOSITING) + if (Platform::userInterfaceThreadMessageClient()->isCurrentThread()) + return m_compositor && m_compositor->drawsRootLayer(); + + // WebKit thread implementation: + RenderView* renderView = m_mainFrame->contentRenderer(); + if (!renderView || !renderView->layer() || !renderView->layer()->backing()) + return false; + + return !renderView->layer()->backing()->paintingGoesToWindow(); +#else + return false; +#endif +} + +void WebPagePrivate::setCompositorDrawsRootLayer(bool compositorDrawsRootLayer) +{ +#if USE(ACCELERATED_COMPOSITING) + if (m_page->settings()->forceCompositingMode() == compositorDrawsRootLayer) + return; + + // When the BlackBerry port forces compositing mode, the root layer stops + // painting to window and starts painting to layer instead. + m_page->settings()->setForceCompositingMode(compositorDrawsRootLayer); + if (FrameView* view = m_mainFrame->view()) + view->updateCompositingLayers(); +#endif +} + #if USE(ACCELERATED_COMPOSITING) void WebPagePrivate::drawLayersOnCommit() { @@ -5055,7 +5497,7 @@ void WebPagePrivate::drawLayersOnCommit() // animations. And only if we don't need a one shot drawing sync. ASSERT(!needsOneShotDrawingSynchronization()); - if (!m_webPage->isVisible() || !m_backingStore->d->isActive()) + if (!m_webPage->isVisible()) return; m_backingStore->d->willDrawLayersOnCommit(); @@ -5065,52 +5507,12 @@ void WebPagePrivate::drawLayersOnCommit() 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; +#if DEBUG_AC_COMMIT + Platform::log(Platform::LogLevelCritical, "%s", WTF_PRETTY_FUNCTION); +#endif - return m_backingStore->d->drawSubLayers(); + if (!m_backingStore->d->shouldDirectRenderingToWindow()) + m_backingStore->d->blitVisibleContents(); } void WebPagePrivate::scheduleRootLayerCommit() @@ -5119,8 +5521,12 @@ void WebPagePrivate::scheduleRootLayerCommit() return; m_needsCommit = true; - if (!m_rootLayerCommitTimer->isActive()) + if (!m_rootLayerCommitTimer->isActive()) { +#if DEBUG_AC_COMMIT + Platform::log(Platform::LogLevelCritical, "%s: m_rootLayerCommitTimer->isActive() = %d", WTF_PRETTY_FUNCTION, m_rootLayerCommitTimer->isActive()); +#endif m_rootLayerCommitTimer->startOneShot(0); + } } static bool needsLayoutRecursive(FrameView* view) @@ -5147,19 +5553,57 @@ LayerRenderingResults WebPagePrivate::lastCompositingResults() const return LayerRenderingResults(); } +void WebPagePrivate::setCompositor(PassRefPtr<WebPageCompositorPrivate> compositor) +{ + using namespace BlackBerry::Platform; + + // The m_compositor member has to be modified during a sync call for thread + // safe access to m_compositor and its refcount. + if (!userInterfaceThreadMessageClient()->isCurrentThread()) { + userInterfaceThreadMessageClient()->dispatchSyncMessage(createMethodCallMessage(&WebPagePrivate::setCompositor, this, compositor)); + return; + } + + m_compositor = compositor; + + // The previous compositor, if any, has now released it's OpenGL resources, + // so we can safely free the owned context, if any. + m_ownedContext.clear(); +} + void WebPagePrivate::commitRootLayer(const IntRect& layoutRectForCompositing, - const IntSize& contentsSizeForCompositing) + const IntSize& contentsSizeForCompositing, + bool drawsRootLayer) { +#if DEBUG_AC_COMMIT + Platform::log(Platform::LogLevelCritical, "%s: m_compositor = 0x%x", + WTF_PRETTY_FUNCTION, m_compositor.get()); +#endif + if (!m_frameLayers || !m_compositor) return; + if (m_frameLayers->rootLayer() && m_frameLayers->rootLayer()->layerCompositingThread() != m_compositor->rootLayer()) + m_compositor->setRootLayer(m_frameLayers->rootLayer()->layerCompositingThread()); + m_compositor->setLayoutRectForCompositing(layoutRectForCompositing); m_compositor->setContentsSizeForCompositing(contentsSizeForCompositing); + m_compositor->setDrawsRootLayer(drawsRootLayer); m_compositor->commit(m_frameLayers->rootLayer()); } bool WebPagePrivate::commitRootLayerIfNeeded() { +#if DEBUG_AC_COMMIT + Platform::log(Platform::LogLevelCritical, "%s: m_suspendRootLayerCommit = %d, m_needsCommit = %d, m_frameLayers = 0x%x, m_frameLayers->hasLayer() = %d, needsLayoutRecursive() = %d", + WTF_PRETTY_FUNCTION, + m_suspendRootLayerCommit, + m_needsCommit, + m_frameLayers.get(), + m_frameLayers && m_frameLayers->hasLayer(), + m_mainFrame && m_mainFrame->view() && needsLayoutRecursive(m_mainFrame->view())); +#endif + if (m_suspendRootLayerCommit) return false; @@ -5199,6 +5643,7 @@ bool WebPagePrivate::commitRootLayerIfNeeded() // and that's what the layer renderer wants. IntRect layoutRectForCompositing(scrollPosition(), actualVisibleSize()); IntSize contentsSizeForCompositing = contentsSize(); + bool drawsRootLayer = compositorDrawsRootLayer(); // Commit changes made to the layers synchronously with the compositing thread. Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage( @@ -5206,7 +5651,8 @@ bool WebPagePrivate::commitRootLayerIfNeeded() &WebPagePrivate::commitRootLayer, this, layoutRectForCompositing, - contentsSizeForCompositing)); + contentsSizeForCompositing, + drawsRootLayer)); return true; } @@ -5216,6 +5662,10 @@ void WebPagePrivate::rootLayerCommitTimerFired(Timer<WebPagePrivate>*) if (m_suspendRootLayerCommit) return; +#if DEBUG_AC_COMMIT + Platform::log(Platform::LogLevelCritical, "%s", WTF_PRETTY_FUNCTION); +#endif + // 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 @@ -5224,20 +5674,30 @@ void WebPagePrivate::rootLayerCommitTimerFired(Timer<WebPagePrivate>*) // 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 we transitioned to drawing the root layer using compositor instead of + // backing store, doing a one shot drawing synchronization with the + // backing store is never necessary, because the backing store draws + // nothing. + if (!compositorDrawsRootLayer()) { + bool isSingleTargetWindow = SurfacePool::globalSurfacePool()->compositingSurface() + || m_backingStore->d->isOpenGLCompositing(); + + // 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()) { +#if DEBUG_AC_COMMIT + Platform::log(Platform::LogLevelCritical, "%s: OneShotDrawingSynchronization code path!", WTF_PRETTY_FUNCTION); +#endif - if (needsOneShotDrawingSynchronization()) { - const IntRect windowRect = IntRect(IntPoint::zero(), viewportSize()); - m_backingStore->d->repaint(windowRect, true /*contentChanged*/, true /*immediate*/); - return; + 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. @@ -5246,28 +5706,6 @@ void WebPagePrivate::rootLayerCommitTimerFired(Timer<WebPagePrivate>*) 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()) { @@ -5319,19 +5757,13 @@ void WebPagePrivate::setRootLayerCompositingThread(LayerCompositingThread* 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); + // Keep the compositor around, a single web page will frequently enter + // and leave compositing mode many times. Instead we destroy it when + // navigating to a new page. + resetCompositingSurface(); + } else if (!m_compositor) + createCompositor(); // Don't ASSERT(m_compositor) here because setIsAcceleratedCompositingActive(true) // may not turn accelerated compositing on since m_backingStore is 0. @@ -5339,9 +5771,34 @@ void WebPagePrivate::setRootLayerCompositingThread(LayerCompositingThread* layer m_compositor->setRootLayer(layer); } +bool WebPagePrivate::createCompositor() +{ + // If there's no window, the compositor will be supplied by the API client + if (!m_client->window()) + return false; + + m_ownedContext = GLES2Context::create(this); + m_compositor = WebPageCompositorPrivate::create(this, 0); + m_compositor->setContext(m_ownedContext.get()); + + if (!m_compositor->hardwareCompositing()) { + destroyCompositor(); + return false; + } + + return true; +} + void WebPagePrivate::destroyCompositor() { - m_compositor.clear(); + // We shouldn't release the compositor unless we created and own the + // context. If the compositor was created from the WebPageCompositor API, + // keep it around and reuse it later. + if (!m_ownedContext) + return; + + m_compositor.clear(); + m_ownedContext.clear(); } void WebPagePrivate::syncDestroyCompositorOnCompositingThread() @@ -5366,7 +5823,7 @@ void WebPagePrivate::suspendRootLayerCommit() m_suspendRootLayerCommit = true; - if (!m_frameLayers || !m_frameLayers->hasLayer() || !m_compositor) + if (!m_compositor) return; Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage( @@ -5392,6 +5849,11 @@ bool WebPagePrivate::needsOneShotDrawingSynchronization() void WebPagePrivate::setNeedsOneShotDrawingSynchronization() { + if (compositorDrawsRootLayer()) { + scheduleRootLayerCommit(); + return; + } + // This means we have to commit layers on next render, or render on the next commit, // whichever happens first. m_needsCommit = true; @@ -5477,9 +5939,6 @@ void WebPagePrivate::didChangeSettings(WebSettings* webSettings) 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(); @@ -5599,5 +6058,24 @@ void WebPagePrivate::frameUnloaded(const Frame* frame) m_inPageSearchManager->frameUnloaded(frame); } +const String& WebPagePrivate::defaultUserAgent() +{ + static String* defaultUserAgent = new String; + if (defaultUserAgent->isEmpty()) { + BlackBerry::Platform::DeviceInfo* info = BlackBerry::Platform::DeviceInfo::instance(); + char uaBuffer[256]; + int uaSize = snprintf(uaBuffer, 256, "Mozilla/5.0 (%s) AppleWebKit/%d.%d+ (KHTML, like Gecko) Version/%s %sSafari/%d.%d+", + info->family(), WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION, info->osVersion(), + info->isMobile() ? "Mobile " : "", WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION); + + if (uaSize <= 0 || uaSize >= 256) + BLACKBERRY_CRASH(); + + defaultUserAgent->append(uaBuffer); + } + + return *defaultUserAgent; +} + } } |
