#include "config.h"
#include "WebPage.h"
#include "APIShims.h"
#include "ApplicationCacheStorage.h"
#include "AuthenticationChallengeManager.h"
#include "AutofillManager.h"
#include "BackForwardController.h"
#include "BackForwardListBlackBerry.h"
#include "BackingStoreClient.h"
#include "BackingStore_p.h"
#if ENABLE(BATTERY_STATUS)
#include "BatteryClientBlackBerry.h"
#endif
#include "CachedImage.h"
#include "Chrome.h"
#include "ChromeClientBlackBerry.h"
#include "CookieManager.h"
#include "CredentialManager.h"
#include "CredentialStorage.h"
#include "CredentialTransformData.h"
#include "DOMSupport.h"
#include "DatabaseManager.h"
#include "DefaultTapHighlight.h"
#include "DeviceMotionClientBlackBerry.h"
#include "DeviceOrientationClientBlackBerry.h"
#if !defined(PUBLIC_BUILD) || !PUBLIC_BUILD
#include "DeviceOrientationClientMock.h"
#endif
#include "DragClientBlackBerry.h"
#if !defined(PUBLIC_BUILD) || !PUBLIC_BUILD
#include "DumpRenderTreeBlackBerry.h"
#endif
#include "EditorClientBlackBerry.h"
#include "FocusController.h"
#include "Frame.h"
#include "FrameLoadRequest.h"
#include "FrameLoaderClientBlackBerry.h"
#if !defined(PUBLIC_BUILD) || !PUBLIC_BUILD
#include "GeolocationClientMock.h"
#endif
#include "GeolocationClientBlackBerry.h"
#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"
#include "HistoryItem.h"
#include "IconDatabaseClientBlackBerry.h"
#include "ImageDocument.h"
#include "InPageSearchManager.h"
#include "InRegionScrollableArea.h"
#include "InRegionScroller_p.h"
#include "InputHandler.h"
#include "InspectorBackendDispatcher.h"
#include "InspectorClientBlackBerry.h"
#include "InspectorController.h"
#include "InspectorInstrumentation.h"
#include "InspectorOverlay.h"
#include "JavaScriptVariant_p.h"
#include "LayerWebKitThread.h"
#include "LocalFileSystem.h"
#if ENABLE(NETWORK_INFO)
#include "NetworkInfoClientBlackBerry.h"
#endif
#include "NetworkManager.h"
#include "NodeRenderStyle.h"
#include "NodeTraversal.h"
#if ENABLE(NAVIGATOR_CONTENT_UTILS)
#include "NavigatorContentUtilsClientBlackBerry.h"
#endif
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
#include "NotificationClientBlackBerry.h"
#endif
#include "Page.h"
#include "PageCache.h"
#include "PageGroup.h"
#include "PagePopup.h"
#include "PagePopupClient.h"
#include "PlatformTouchEvent.h"
#include "PlatformWheelEvent.h"
#include "PluginDatabase.h"
#include "PluginView.h"
#include "RenderLayerBacking.h"
#include "RenderLayerCompositor.h"
#if ENABLE(FULLSCREEN_API)
#include "RenderFullScreen.h"
#endif
#include "RenderText.h"
#include "RenderThemeBlackBerry.h"
#include "RenderTreeAsText.h"
#include "RenderView.h"
#include "RenderWidget.h"
#include "ScriptController.h"
#include "ScriptSourceCode.h"
#include "ScriptValue.h"
#include "ScrollTypes.h"
#include "SecurityPolicy.h"
#include "SelectionHandler.h"
#include "SelectionOverlay.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"
#if ENABLE(MEDIA_STREAM)
#include "UserMediaClientImpl.h"
#endif
#if ENABLE(VIBRATION)
#include "VibrationClientBlackBerry.h"
#endif
#include "VisiblePosition.h"
#include "WebCookieJar.h"
#include "WebKitThreadViewportAccessor.h"
#include "WebKitVersion.h"
#include "WebOverlay.h"
#include "WebOverlay_p.h"
#include "WebPageClient.h"
#include "WebSocket.h"
#include "WebViewportArguments.h"
#include "npapi.h"
#include "runtime_root.h"
#if ENABLE(VIDEO)
#include "MediaPlayer.h"
#include "MediaPlayerPrivateBlackBerry.h"
#endif
#if USE(ACCELERATED_COMPOSITING)
#include "FrameLayers.h"
#include "WebPageCompositorClient.h"
#include "WebPageCompositor_p.h"
#endif
#include <BlackBerryPlatformDeviceInfo.h>
#include <BlackBerryPlatformExecutableMessage.h>
#include <BlackBerryPlatformKeyboardEvent.h>
#include <BlackBerryPlatformMessageClient.h>
#include <BlackBerryPlatformMouseEvent.h>
#include <BlackBerryPlatformScreen.h>
#include <BlackBerryPlatformSettings.h>
#include <BlackBerryPlatformWebFileSystem.h>
#include <JavaScriptCore/APICast.h>
#include <JavaScriptCore/JSContextRef.h>
#include <JavaScriptCore/JSStringRef.h>
#include <SharedPointer.h>
#include <cmath>
#include <sys/keycodes.h>
#include <unicode/ustring.h> // platform ICU
#include <wtf/text/CString.h>
#ifndef USER_PROCESSES
#include <memalloc.h>
#endif
#if ENABLE(REQUEST_ANIMATION_FRAME)
#include "PlatformScreen.h"
#endif
#define DEBUG_TOUCH_EVENTS 0
#define DEBUG_WEBPAGE_LOAD 0
#define DEBUG_AC_COMMIT 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; if (!s_visibleWebPages)
s_visibleWebPages = new Vector<WebPage*>;
return s_visibleWebPages;
}
const unsigned blockZoomMargin = 3; static int blockClickRadius = 0;
static double maximumBlockZoomScale = 3;
const double manualScrollInterval = 0.1;
const IntSize minimumLayoutSize(10, 10);
const double minimumExpandingRatio = 0.15;
const double minimumZoomToFitScale = 0.25;
const double maximumImageDocumentZoomToFitScale = 2;
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;
}
static inline WebCore::PlatformEvent::Type toWebCoreMouseEventType(const BlackBerry::Platform::MouseEvent::Type type)
{
switch (type) {
case BlackBerry::Platform::MouseEvent::MouseButtonDown:
return WebCore::PlatformEvent::MousePressed;
case Platform::MouseEvent::MouseButtonUp:
return WebCore::PlatformEvent::MouseReleased;
case Platform::MouseEvent::MouseMove:
default:
return WebCore::PlatformEvent::MouseMoved;
}
}
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);
}
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;
};
void WebPage::autofillTextField(const BlackBerry::Platform::String& item)
{
if (!d->m_webSettings->isFormAutofillEnabled())
return;
d->m_autofillManager->autofillTextField(item);
}
BlackBerry::Platform::String WebPage::renderTreeAsText()
{
return externalRepresentation(d->m_mainFrame);
}
WebPagePrivate::WebPagePrivate(WebPage* webPage, WebPageClient* client, const IntRect& rect)
: m_webPage(webPage)
, m_client(client)
, m_inspectorClient(0)
, m_page(0) , m_mainFrame(0) , m_currentContextNode(0)
, m_webSettings(0) , m_cookieJar(0)
, m_visible(false)
, m_activationState(ActivationActive)
, m_shouldResetTilesWhenShown(false)
, m_shouldZoomToInitialScaleAfterLoadFinished(false)
, m_userScalable(true)
, m_userPerformedManualZoom(false)
, m_userPerformedManualScroll(false)
, m_contentsSizeChanged(false)
, m_overflowExceedsContentsSize(false)
, m_resetVirtualViewportOnCommitted(true)
, m_shouldUseFixedDesktopMode(false)
, m_inspectorEnabled(false)
, m_preventIdleDimmingCount(0)
#if ENABLE(TOUCH_EVENTS)
, m_preventDefaultOnTouchStart(false)
#endif
, m_nestedLayoutFinishedCount(0)
, m_actualVisibleWidth(rect.width())
, m_actualVisibleHeight(rect.height())
, m_defaultLayoutSize(minimumLayoutSize)
, m_didRestoreFromPageCache(false)
, m_viewMode(WebPagePrivate::Desktop) , m_loadState(WebPagePrivate::None)
, m_transformationMatrix(new TransformationMatrix())
, m_backingStore(0) , m_backingStoreClient(0) , m_webkitThreadViewportAccessor(new WebKitThreadViewportAccessor(this))
, m_inPageSearchManager(new InPageSearchManager(this))
, m_inputHandler(new InputHandler(this))
, m_selectionHandler(new SelectionHandler(this))
, m_touchEventHandler(new TouchEventHandler(this))
, m_proximityDetector(new ProximityDetector(this))
#if ENABLE(EVENT_MODE_METATAGS)
, m_cursorEventMode(ProcessedCursorEvents)
, m_touchEventMode(ProcessedTouchEvents)
#endif
#if ENABLE(FULLSCREEN_API) && ENABLE(VIDEO)
, m_scaleBeforeFullScreen(-1.0)
#endif
, m_currentCursor(Platform::CursorNone)
, m_dumpRenderTree(0) , m_initialScale(-1.0)
, m_minimumScale(-1.0)
, m_maximumScale(-1.0)
, m_forceRespectViewportArguments(false)
, m_anchorInNodeRectRatio(-1, -1)
, m_currentBlockZoomNode(0)
, m_currentBlockZoomAdjustedNode(0)
, m_shouldReflowBlock(false)
, m_lastUserEventTimestamp(0.0)
, m_pluginMouseButtonPressed(false)
, m_pluginMayOpenNewTab(false)
#if USE(ACCELERATED_COMPOSITING)
, m_rootLayerCommitTimer(adoptPtr(new Timer<WebPagePrivate>(this, &WebPagePrivate::rootLayerCommitTimerFired)))
, m_needsOneShotDrawingSynchronization(false)
, m_needsCommit(false)
, m_suspendRootLayerCommit(false)
#endif
, m_pendingOrientation(-1)
, m_fullscreenNode(0)
, m_hasInRegionScrollableAreas(false)
, m_updateDelegatedOverlaysDispatched(false)
, m_deferredTasksTimer(this, &WebPagePrivate::deferredTasksTimerFired)
, m_pagePopup(0)
, m_autofillManager(AutofillManager::create(this))
, m_documentStyleRecalcPostponed(false)
, m_documentChildNeedsStyleRecalc(false)
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
, m_notificationManager(this)
#endif
, m_didStartAnimations(false)
, m_animationStartTime(0)
#if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER)
, m_isRunningRefreshAnimationClient(false)
, m_animationScheduled(false)
, m_previousFrameDone(true)
, m_monotonicAnimationStartTime(0)
#endif
{
static bool isInitialized = false;
if (!isInitialized) {
isInitialized = true;
BlackBerry::Platform::DeviceInfo::instance();
defaultUserAgent();
}
AuthenticationChallengeManager::instance()->pageCreated(this);
clearCachedHitTestResult();
}
WebPage::WebPage(WebPageClient* client, const BlackBerry::Platform::String& pageGroupName, const Platform::IntRect& rect)
{
globalInitialize();
d = new WebPagePrivate(this, client, rect);
d->init(pageGroupName);
}
WebPagePrivate::~WebPagePrivate()
{
m_webPage->setVisible(false);
if (BackingStorePrivate::currentBackingStoreOwner() == m_webPage)
BackingStorePrivate::setCurrentBackingStoreOwner(0);
#if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER)
stopRefreshAnimationClient();
cancelCallOnMainThread(handleServiceScriptedAnimationsOnMainThread, this);
#endif
closePagePopup();
delete m_webSettings;
m_webSettings = 0;
delete m_cookieJar;
m_cookieJar = 0;
delete m_webkitThreadViewportAccessor;
m_webkitThreadViewportAccessor = 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;
delete m_proximityDetector;
m_proximityDetector = 0;
#if !defined(PUBLIC_BUILD) || !PUBLIC_BUILD
BlackBerry::Platform::deleteGuardedObject(static_cast<DumpRenderTree*>(m_dumpRenderTree));
m_dumpRenderTree = 0;
#endif
AuthenticationChallengeManager::instance()->pageDeleted(this);
}
WebPage::~WebPage()
{
deleteGuardedObject(d);
d = 0;
}
Page* WebPagePrivate::core(const WebPage* webPage)
{
return webPage->d->m_page;
}
void WebPagePrivate::init(const BlackBerry::Platform::String& pageGroupName)
{
m_webSettings = WebSettings::createFromStandardSettings();
m_webSettings->setUserAgentString(defaultUserAgent());
ChromeClientBlackBerry* chromeClient = new ChromeClientBlackBerry(this);
EditorClientBlackBerry* editorClient = new EditorClientBlackBerry(this);
DragClientBlackBerry* dragClient = 0;
#if ENABLE(DRAG_SUPPORT)
dragClient = new DragClientBlackBerry();
#endif
#if ENABLE(INSPECTOR)
m_inspectorClient = new InspectorClientBlackBerry(this);
#endif
FrameLoaderClientBlackBerry* frameLoaderClient = new FrameLoaderClientBlackBerry();
Page::PageClients pageClients;
pageClients.chromeClient = chromeClient;
pageClients.editorClient = editorClient;
pageClients.dragClient = dragClient;
pageClients.inspectorClient = m_inspectorClient;
pageClients.backForwardClient = BackForwardListBlackBerry::create(this);
m_page = new Page(pageClients);
#if !defined(PUBLIC_BUILD) || !PUBLIC_BUILD
if (isRunningDrt()) {
GeolocationClientMock* mock = new GeolocationClientMock();
WebCore::provideGeolocationTo(m_page, mock);
mock->setController(WebCore::GeolocationController::from(m_page));
} else
#endif
WebCore::provideGeolocationTo(m_page, new GeolocationClientBlackBerry(this));
#if !defined(PUBLIC_BUILD) || !PUBLIC_BUILD
if (getenv("drtRun"))
WebCore::provideDeviceOrientationTo(m_page, new DeviceOrientationClientMock);
else
#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
#if ENABLE(BATTERY_STATUS)
WebCore::provideBatteryTo(m_page, new WebCore::BatteryClientBlackBerry(this));
#endif
#if ENABLE(MEDIA_STREAM)
WebCore::provideUserMediaTo(m_page, new UserMediaClientImpl(m_webPage));
#endif
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
WebCore::provideNotification(m_page, new NotificationClientBlackBerry(this));
#endif
#if ENABLE(NAVIGATOR_CONTENT_UTILS)
m_navigatorContentUtilsClient = adoptPtr(new NavigatorContentUtilsClientBlackBerry(this));
WebCore::provideNavigatorContentUtilsTo(m_page, m_navigatorContentUtilsClient.get());
#endif
#if ENABLE(NETWORK_INFO)
WebCore::provideNetworkInfoTo(m_page, new WebCore::NetworkInfoClientBlackBerry(this));
#endif
m_page->setDeviceScaleFactor(m_webSettings->devicePixelRatio());
m_page->addLayoutMilestones(DidFirstVisuallyNonEmptyLayout);
#if USE(ACCELERATED_COMPOSITING)
m_tapHighlight = DefaultTapHighlight::create(this);
m_selectionHighlight = DefaultTapHighlight::create(this);
m_selectionOverlay = SelectionOverlay::create(this);
m_page->settings()->setAcceleratedCompositingForFixedPositionEnabled(true);
#endif
m_webSettings->setPageGroupName(pageGroupName);
m_webSettings->setDelegate(this);
didChangeSettings(m_webSettings);
RefPtr<Frame> newFrame = Frame::create(m_page, 0, frameLoaderClient);
m_mainFrame = newFrame.get();
frameLoaderClient->setFrame(m_mainFrame, this);
m_mainFrame->init();
m_inRegionScroller = adoptPtr(new InRegionScroller(this));
#if ENABLE(WEBGL)
m_page->settings()->setWebGLEnabled(true);
#endif
#if ENABLE(ACCELERATED_2D_CANVAS)
m_page->settings()->setCanvasUsesAcceleratedDrawing(true);
m_page->settings()->setAccelerated2dCanvasEnabled(true);
#endif
m_page->settings()->setInteractiveFormValidationEnabled(true);
m_page->settings()->setAllowUniversalAccessFromFileURLs(false);
m_page->settings()->setAllowFileAccessFromFileURLs(false);
m_page->settings()->setFixedPositionCreatesStackingContext(true);
m_page->settings()->setWantsBalancedSetDefersLoadingBehavior(true);
m_backingStoreClient = BackingStoreClient::create(m_mainFrame, 0, m_webPage);
m_backingStore = m_backingStoreClient->backingStore();
blockClickRadius = int(roundf(0.35 * Platform::Graphics::Screen::primaryScreen()->pixelsPerInch(0).width()));
m_page->settings()->setDelegateSelectionPaint(true);
#if ENABLE(REQUEST_ANIMATION_FRAME)
m_page->windowScreenDidChange((PlatformDisplayID)0);
#endif
#if ENABLE(FILE_SYSTEM)
static bool localFileSystemInitialized = false;
if (!localFileSystemInitialized) {
localFileSystemInitialized = true;
WebCore::LocalFileSystem::initializeLocalFileSystem("/");
}
#endif
#if USE(ACCELERATED_COMPOSITING)
Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage(
createMethodCallMessage(&WebPagePrivate::createCompositor, this));
#endif
}
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 Platform::NetworkRequest& netReq, bool needReferer)
{
stopCurrentLoad();
DeferredTaskLoadManualScript::finishOrCancel(this);
String urlString(netReq.getUrlRef());
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")) {
if (m_page->defersLoading())
m_deferredTasks.append(adoptPtr(new DeferredTaskLoadManualScript(this, kurl)));
else
m_mainFrame->script()->executeIfJavaScriptURL(kurl, DoNotReplaceDocumentIfJavaScriptURL);
return;
}
ResourceRequest request(kurl);
request.setHTTPMethod(netReq.getMethodRef());
request.setCachePolicy(toWebCoreCachePolicy(netReq.getCachePolicy()));
if (!netReq.getOverrideContentType().empty())
request.setOverrideContentType(netReq.getOverrideContentType());
Platform::NetworkRequest::HeaderList& list = netReq.getHeaderListRef();
if (!list.empty()) {
for (unsigned i = 0; i < list.size(); i++)
request.addHTTPHeaderField(list[i].first.c_str(), list[i].second.c_str());
}
if (needReferer && focusedOrMainFrame() && focusedOrMainFrame()->document())
request.addHTTPHeaderField("Referer", focusedOrMainFrame()->document()->url().string().utf8().data());
if (Platform::NetworkRequest::TargetIsDownload == netReq.getTargetType())
request.setForceDownload(true);
if (!netReq.getSuggestedSaveName().empty())
request.setSuggestedSaveName(netReq.getSuggestedSaveName());
m_mainFrame->loader()->load(FrameLoadRequest(m_mainFrame, request));
}
void WebPage::loadFile(const BlackBerry::Platform::String& path, const BlackBerry::Platform::String& overrideContentType)
{
STATIC_LOCAL_STRING(s_filePrefix, "file://");
STATIC_LOCAL_STRING(s_fileRootPrefix, "file:///");
BlackBerry::Platform::String fileUrl(path);
if (fileUrl.startsWith('/'))
fileUrl = s_filePrefix + fileUrl;
else if (!fileUrl.startsWith(s_fileRootPrefix))
return;
Platform::NetworkRequest netRequest;
netRequest.setRequestUrl(fileUrl);
netRequest.setOverrideContentType(overrideContentType);
d->load(netRequest, false);
}
void WebPage::load(const Platform::NetworkRequest& request, bool needReferer)
{
d->load(request, needReferer);
}
void WebPagePrivate::loadString(const BlackBerry::Platform::String& string, const BlackBerry::Platform::String& baseURL, const BlackBerry::Platform::String& contentType, const BlackBerry::Platform::String& failingURL)
{
KURL kurl = parseUrl(baseURL);
ResourceRequest request(kurl);
WTF::RefPtr<SharedBuffer> buffer
= SharedBuffer::create(string.c_str(), string.length());
SubstituteData substituteData(buffer,
extractMIMETypeFromMediaType(contentType),
extractCharsetFromMediaType(contentType),
!failingURL.empty() ? parseUrl(failingURL) : KURL());
m_mainFrame->loader()->load(FrameLoadRequest(m_mainFrame, request, substituteData));
}
void WebPage::loadString(const BlackBerry::Platform::String& string, const BlackBerry::Platform::String& baseURL, const BlackBerry::Platform::String& mimeType, const BlackBerry::Platform::String& failingURL)
{
d->loadString(string, baseURL, mimeType, failingURL);
}
bool WebPagePrivate::executeJavaScript(const BlackBerry::Platform::String& scriptUTF8, JavaScriptDataType& returnType, BlackBerry::Platform::String& returnValue)
{
BLACKBERRY_ASSERT(scriptUTF8.isUtf8());
String script = scriptUTF8;
if (script.isNull()) {
returnType = JSException;
return false;
}
if (script.isEmpty()) {
returnType = JSUndefined;
return true;
}
ScriptValue result = m_mainFrame->script()->executeScript(script, false);
JSC::JSValue value = result.jsValue();
if (!value) {
returnType = JSException;
return false;
}
if (value.isUndefined())
returnType = JSUndefined;
else if (value.isNull())
returnType = JSNull;
else if (value.isBoolean())
returnType = JSBoolean;
else if (value.isNumber())
returnType = JSNumber;
else if (value.isString())
returnType = JSString;
else if (value.isObject())
returnType = JSObject;
else
returnType = JSUndefined;
if (returnType == JSBoolean || returnType == JSNumber || returnType == JSString || returnType == JSObject) {
JSC::ExecState* exec = m_mainFrame->script()->globalObject(mainThreadNormalWorld())->globalExec();
returnValue = result.toString(exec);
}
return true;
}
bool WebPage::executeJavaScript(const BlackBerry::Platform::String& script, JavaScriptDataType& returnType, BlackBerry::Platform::String& returnValue)
{
return d->executeJavaScript(script, returnType, returnValue);
}
bool WebPagePrivate::executeJavaScriptInIsolatedWorld(const ScriptSourceCode& sourceCode, JavaScriptDataType& returnType, BlackBerry::Platform::String& returnValue)
{
if (!m_isolatedWorld)
m_isolatedWorld = m_mainFrame->script()->createWorld();
ScriptValue result = m_mainFrame->script()->evaluateInWorld(sourceCode, m_isolatedWorld.get());
JSC::JSValue value = result.jsValue();
if (!value) {
returnType = JSException;
return false;
}
if (value.isUndefined())
returnType = JSUndefined;
else if (value.isNull())
returnType = JSNull;
else if (value.isBoolean())
returnType = JSBoolean;
else if (value.isNumber())
returnType = JSNumber;
else if (value.isString())
returnType = JSString;
else if (value.isObject())
returnType = JSObject;
else
returnType = JSUndefined;
if (returnType == JSBoolean || returnType == JSNumber || returnType == JSString || returnType == JSObject) {
JSC::ExecState* exec = m_mainFrame->script()->globalObject(mainThreadNormalWorld())->globalExec();
returnValue = result.toString(exec);
}
return true;
}
bool WebPage::executeJavaScriptInIsolatedWorld(const std::wstring& script, JavaScriptDataType& returnType, BlackBerry::Platform::String& returnValue)
{
int lengthCopied = 0;
UErrorCode error = U_ZERO_ERROR;
const int length = script.length() + 1 ;
UChar data[length];
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 BlackBerry::Platform::String& scriptUTF8, JavaScriptDataType& returnType, BlackBerry::Platform::String& returnValue)
{
BLACKBERRY_ASSERT(scriptUTF8.isUtf8());
ScriptSourceCode sourceCode(scriptUTF8, KURL());
return d->executeJavaScriptInIsolatedWorld(sourceCode, returnType, returnValue);
}
void WebPage::executeJavaScriptFunction(const std::vector<BlackBerry::Platform::String> &function, const std::vector<JavaScriptVariant> &args, JavaScriptVariant& returnValue)
{
if (!d->m_mainFrame) {
returnValue.setType(JavaScriptVariant::Exception);
return;
}
JSC::Bindings::RootObject* root = d->m_mainFrame->script()->bindingRootObject();
if (!root) {
returnValue.setType(JavaScriptVariant::Exception);
return;
}
JSC::ExecState* exec = root->globalObject()->globalExec();
JSGlobalContextRef ctx = toGlobalRef(exec);
JSC::APIEntryShim shim(exec);
WTF::Vector<JSValueRef> argListRef(args.size());
for (unsigned i = 0; i < args.size(); ++i)
argListRef[i] = BlackBerryJavaScriptVariantToJSValueRef(ctx, args[i]);
JSValueRef windowObjectValue = toRef(d->m_mainFrame->script()->globalObject(mainThreadNormalWorld()));
JSObjectRef obj = JSValueToObject(ctx, windowObjectValue, 0);
JSObjectRef thisObject = obj;
for (unsigned i = 0; i < function.size(); ++i) {
JSStringRef str = JSStringCreateWithUTF8CString(function[i].c_str());
thisObject = obj;
obj = JSValueToObject(ctx, JSObjectGetProperty(ctx, obj, str, 0), 0);
JSStringRelease(str);
if (!obj)
break;
}
JSObjectRef functionObject = obj;
JSValueRef result = 0;
if (functionObject && thisObject)
result = JSObjectCallAsFunction(ctx, functionObject, thisObject, args.size(), argListRef.data(), 0);
if (!result) {
returnValue.setType(JavaScriptVariant::Exception);
return;
}
returnValue = JSValueRefToBlackBerryJavaScriptVariant(ctx, result);
}
void WebPagePrivate::stopCurrentLoad()
{
m_mainFrame->loader()->stopAllLoaders();
DeferredTaskLoadManualScript::finishOrCancel(this);
}
void WebPage::stopLoading()
{
d->stopCurrentLoad();
}
static void closeURLRecursively(Frame* frame)
{
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()
{
closeURLRecursively(m_mainFrame);
}
void WebPage::prepareToDestroy()
{
d->prepareToDestroy();
}
bool WebPage::dispatchBeforeUnloadEvent()
{
return d->m_page->mainFrame()->loader()->shouldClose();
}
static void enableCrossSiteXHRRecursively(Frame* frame)
{
frame->document()->securityOrigin()->grantUniversalAccess();
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++)
enableCrossSiteXHRRecursively(childFrames[i].get());
}
void WebPagePrivate::enableCrossSiteXHR()
{
enableCrossSiteXHRRecursively(m_mainFrame);
}
void WebPage::enableCrossSiteXHR()
{
d->enableCrossSiteXHR();
}
void WebPagePrivate::addOriginAccessWhitelistEntry(const BlackBerry::Platform::String& sourceOrigin, const BlackBerry::Platform::String& destinationOrigin, bool allowDestinationSubdomains)
{
RefPtr<SecurityOrigin> source = SecurityOrigin::createFromString(sourceOrigin);
if (source->isUnique())
return;
KURL destination(KURL(), destinationOrigin);
SecurityPolicy::addOriginAccessWhitelistEntry(*source, destination.protocol(), destination.host(), allowDestinationSubdomains);
}
void WebPage::addOriginAccessWhitelistEntry(const BlackBerry::Platform::String& sourceOrigin, const BlackBerry::Platform::String& destinationOrigin, bool allowDestinationSubdomains)
{
d->addOriginAccessWhitelistEntry(sourceOrigin, destinationOrigin, allowDestinationSubdomains);
}
void WebPagePrivate::removeOriginAccessWhitelistEntry(const BlackBerry::Platform::String& sourceOrigin, const BlackBerry::Platform::String& destinationOrigin, bool allowDestinationSubdomains)
{
RefPtr<SecurityOrigin> source = SecurityOrigin::createFromString(sourceOrigin);
if (source->isUnique())
return;
KURL destination(KURL(), destinationOrigin);
SecurityPolicy::removeOriginAccessWhitelistEntry(*source, destination.protocol(), destination.host(), allowDestinationSubdomains);
}
void WebPage::removeOriginAccessWhitelistEntry(const BlackBerry::Platform::String& sourceOrigin, const BlackBerry::Platform::String& destinationOrigin, bool allowDestinationSubdomains)
{
d->removeOriginAccessWhitelistEntry(sourceOrigin, destinationOrigin, allowDestinationSubdomains);
}
void WebPagePrivate::setLoadState(LoadState state)
{
if (m_loadState == state)
return;
bool isFirstLoad = m_loadState == None;
if (state == Finished && m_mainFrame && m_mainFrame->document())
m_mainFrame->document()->updateStyleIfNeeded();
m_backingStore->d->setWebPageBackgroundColor(documentBackgroundColor());
m_loadState = state;
#if DEBUG_WEBPAGE_LOAD
Platform::logAlways(Platform::LogLevelInfo, "WebPagePrivate::setLoadState %d", state);
#endif
switch (m_loadState) {
case Provisional:
if (isFirstLoad) {
m_backingStore->d->renderAndBlitVisibleContentsImmediately();
}
break;
case Committed:
{
#if USE(ACCELERATED_COMPOSITING)
releaseLayerResources();
#endif
m_backingStore->d->suspendBackingStoreUpdates();
m_backingStore->d->suspendScreenUpdates();
m_previousContentsSize = IntSize();
m_backingStore->d->resetRenderQueue();
m_backingStore->d->resetTiles();
m_backingStore->d->setScrollingOrZooming(false, false );
m_shouldZoomToInitialScaleAfterLoadFinished = false;
m_userPerformedManualZoom = false;
m_userPerformedManualScroll = false;
m_shouldUseFixedDesktopMode = false;
m_forceRespectViewportArguments = false;
if (m_resetVirtualViewportOnCommitted) m_virtualViewportSize = IntSize();
if (m_webSettings->viewportWidth() > 0)
m_virtualViewportSize = IntSize(m_webSettings->viewportWidth(), m_defaultLayoutSize.height());
static ViewportArguments defaultViewportArguments;
bool documentHasViewportArguments = false;
if (m_mainFrame && m_mainFrame->document() && m_mainFrame->document()->viewportArguments() != defaultViewportArguments)
documentHasViewportArguments = true;
if (!(m_didRestoreFromPageCache && documentHasViewportArguments)) {
m_viewportArguments = ViewportArguments();
m_userScalable = m_webSettings->isUserScalable();
resetScales();
dispatchViewportPropertiesDidChange(m_userViewportArguments);
if (m_userViewportArguments != defaultViewportArguments)
m_forceRespectViewportArguments = true;
} else {
Platform::IntSize virtualViewport = recomputeVirtualViewportFromViewportArguments();
m_webPage->setVirtualViewportSize(virtualViewport);
}
if (m_shouldUseFixedDesktopMode)
setViewMode(FixedDesktop);
else
setViewMode(Desktop);
#if ENABLE(EVENT_MODE_METATAGS)
didReceiveCursorEventMode(ProcessedCursorEvents);
didReceiveTouchEventMode(ProcessedTouchEvents);
#endif
resetBlockZoom();
#if ENABLE(VIEWPORT_REFLOW)
toggleTextReflowIfEnabledForBlockZoomOnly();
#endif
m_inputHandler->setInputModeEnabled(false);
setScrollPosition(IntPoint::zero());
notifyTransformedScrollChanged();
m_backingStore->d->resumeBackingStoreUpdates();
m_backingStore->d->resumeScreenUpdates(BackingStore::RenderAndBlit);
updateCursor();
break;
}
case Finished:
case Failed:
m_client->scaleChanged();
m_backingStore->d->updateTiles(true , false );
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 || !m_mainFrame->view())
return false;
if (enforceScaleClamping)
scale = this->clampedScale(scale);
ASSERT(clampedScale);
*clampedScale = scale;
if (currentScale() == scale)
return false;
return true;
}
bool WebPagePrivate::zoomAboutPoint(double unclampedScale, const FloatPoint& anchor, bool enforceScaleClamping, bool forceRendering, bool isRestoringZoomLevel)
{
if (!isRestoringZoomLevel) {
resetBlockZoom();
}
#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::logAlways(Platform::LogLevelInfo,
"WebPagePrivate::zoomAboutPoint scale %f anchor %s",
scale, Platform::FloatPoint(anchor).toString().c_str());
}
#endif
FloatPoint scrollPosition = this->scrollPosition();
FloatPoint anchorOffset(anchor.x() - scrollPosition.x(), anchor.y() - scrollPosition.y());
ASSERT(m_transformationMatrix->m11() == m_transformationMatrix->m22());
double inverseScale = scale / m_transformationMatrix->m11();
*m_transformationMatrix = zoom;
m_backingStore->d->suspendBackingStoreUpdates();
m_backingStore->d->suspendScreenUpdates();
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) {
setNeedsLayout();
layoutIfNeeded();
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();
m_backingStore->d->updateTiles(isLoading , false );
bool shouldRender = !isLoading || m_userPerformedManualZoom || forceRendering;
m_client->scaleChanged();
if (m_pendingOrientation != -1)
m_client->updateInteractionViews();
m_backingStore->d->resumeBackingStoreUpdates();
if (shouldRender) {
m_backingStore->d->resumeScreenUpdates(BackingStore::RenderAndBlit);
} else {
m_backingStore->d->resumeScreenUpdates(BackingStore::None);
}
return true;
}
IntPoint WebPagePrivate::calculateReflowedScrollPosition(const FloatPoint& anchorOffset, double inverseScale)
{
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))));
}
void WebPagePrivate::setNeedsLayout()
{
FrameView* view = m_mainFrame->view();
ASSERT(view);
view->setNeedsLayout();
}
void WebPagePrivate::updateLayoutAndStyleIfNeededRecursive() const
{
FrameView* view = m_mainFrame->view();
ASSERT(view);
view->updateLayoutAndStyleIfNeededRecursive();
ASSERT(!view->needsLayout());
}
void WebPagePrivate::layoutIfNeeded() const
{
FrameView* view = m_mainFrame->view();
ASSERT(view);
if (view->needsLayout())
view->layout();
}
IntPoint WebPagePrivate::scrollPosition() const
{
if (!m_backingStoreClient)
return IntPoint();
return m_backingStoreClient->scrollPosition();
}
IntPoint WebPagePrivate::maximumScrollPosition() const
{
if (!m_backingStoreClient)
return IntPoint();
return m_backingStoreClient->maximumScrollPosition();
}
void WebPagePrivate::setScrollPosition(const IntPoint& pos)
{
ASSERT(m_backingStoreClient);
m_backingStoreClient->setScrollPosition(pos);
}
void WebPage::setDocumentScrollPosition(const Platform::IntPoint& documentScrollPosition)
{
WebCore::IntPoint scrollPosition = documentScrollPosition;
if (scrollPosition == d->scrollPosition())
return;
if (currentTime() - d->m_lastUserEventTimestamp < manualScrollInterval)
d->m_userPerformedManualScroll = true;
d->m_backingStoreClient->setIsClientGeneratedScroll(true);
bool constrainsScrollingToContentEdge = d->m_mainFrame->view()->constrainsScrollingToContentEdge();
d->m_mainFrame->view()->setConstrainsScrollingToContentEdge(false);
d->setScrollPosition(scrollPosition);
d->m_mainFrame->view()->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdge);
d->m_backingStoreClient->setIsClientGeneratedScroll(false);
}
bool WebPagePrivate::shouldSendResizeEvent()
{
if (!m_mainFrame || !m_mainFrame->document())
return false;
static const bool unrestrictedResizeEvents = Platform::Settings::instance()->unrestrictedResizeEvents();
if (unrestrictedResizeEvents)
return true;
DocumentLoader* documentLoader = m_mainFrame->loader()->documentLoader();
if (documentLoader && documentLoader->isLoadingInAPISense())
return false;
return true;
}
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);
}
void WebPagePrivate::notifyInRegionScrollStopped()
{
if (m_inRegionScroller->d->isActive())
m_inRegionScroller->d->reset();
}
void WebPage::notifyInRegionScrollStopped()
{
d->notifyInRegionScrollStopped();
}
void WebPagePrivate::setHasInRegionScrollableAreas(bool b)
{
if (b != m_hasInRegionScrollableAreas)
m_hasInRegionScrollableAreas = b;
}
IntSize WebPagePrivate::viewportSize() const
{
return m_webkitThreadViewportAccessor->roundToDocumentFromPixelContents(Platform::IntRect(Platform::IntPoint::zero(), transformedViewportSize())).size();
}
IntSize WebPagePrivate::actualVisibleSize() const
{
return m_webkitThreadViewportAccessor->documentViewportSize();
}
bool WebPagePrivate::hasVirtualViewport() const
{
return !m_virtualViewportSize.isEmpty();
}
void WebPagePrivate::updateViewportSize(bool setFixedReportedSize, bool sendResizeEvent)
{
if (!m_backingStore)
return;
ASSERT(m_mainFrame->view());
IntSize visibleSize = actualVisibleSize();
if (setFixedReportedSize)
m_mainFrame->view()->setFixedReportedSize(visibleSize);
IntRect frameRect = IntRect(scrollPosition(), visibleSize);
if (frameRect != m_mainFrame->view()->frameRect()) {
m_mainFrame->view()->setFrameRect(frameRect);
m_mainFrame->view()->adjustViewSize();
#if ENABLE(FULLSCREEN_API)
adjustFullScreenElementDimensionsIfNeeded();
#endif
}
if (sendResizeEvent && shouldSendResizeEvent())
m_mainFrame->eventHandler()->sendResizeEvent();
m_mainFrame->view()->repaintFixedElementsAfterScrolling();
}
FloatPoint WebPagePrivate::centerOfVisibleContentsRect() const
{
FloatRect visibleContentsRect = this->visibleContentsRect();
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 || !m_mainFrame->view())
return IntSize();
return m_backingStoreClient->contentsSize();
}
IntSize WebPagePrivate::absoluteVisibleOverflowSize() const
{
if (!m_mainFrame || !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;
m_contentsSizeChanged = true;
#if DEBUG_WEBPAGE_LOAD
Platform::logAlways(Platform::LogLevelInfo, "WebPagePrivate::contentsSizeChanged %s", Platform::IntSize(contentsSize).toString().c_str());
#endif
}
void WebPagePrivate::overflowExceedsContentsSize()
{
m_overflowExceedsContentsSize = true;
if (absoluteVisibleOverflowSize().width() < DEFAULT_MAX_LAYOUT_WIDTH && !hasVirtualViewport()) {
if (setViewMode(viewMode())) {
setNeedsLayout();
layoutIfNeeded();
}
}
}
void WebPagePrivate::layoutFinished()
{
m_inputHandler->stopPendingSpellCheckRequests(true );
if (!m_contentsSizeChanged && !m_overflowExceedsContentsSize)
return;
m_contentsSizeChanged = false; m_overflowExceedsContentsSize = false;
if (contentsSize().isEmpty())
return;
if (didLayoutExceedMaximumIterations()) {
notifyTransformedContentsSizeChanged();
return;
}
IntSize previousContentsSize = m_previousContentsSize;
m_nestedLayoutFinishedCount++;
if (shouldZoomToInitialScaleOnLoad()) {
zoomToInitialScaleOnLoad();
m_shouldZoomToInitialScaleAfterLoadFinished = false;
} else if (loadState() != None)
notifyTransformedContentsSizeChanged();
m_nestedLayoutFinishedCount--;
if (!m_nestedLayoutFinishedCount) {
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();
}
const Platform::IntSize pixelContentsSize = m_webkitThreadViewportAccessor->pixelContentsSize();
if ((loadState() == Finished || loadState() == Committed) && (pixelContentsSize.width() < m_actualVisibleWidth || pixelContentsSize.height() < m_actualVisibleHeight))
zoomAboutPoint(initialScale(), newScrollPosition);
}
}
}
void WebPagePrivate::zoomToInitialScaleOnLoad()
{
#if DEBUG_WEBPAGE_LOAD
Platform::logAlways(Platform::LogLevelInfo, "WebPagePrivate::zoomToInitialScaleOnLoad");
#endif
bool needsLayout = false;
if (m_shouldUseFixedDesktopMode)
needsLayout = setViewMode(FixedDesktop);
else
needsLayout = setViewMode(Desktop);
if (needsLayout) {
setNeedsLayout();
}
if (contentsSize().isEmpty()) {
#if DEBUG_WEBPAGE_LOAD
Platform::logAlways(Platform::LogLevelInfo, "WebPagePrivate::zoomToInitialScaleOnLoad content is empty!");
#endif
layoutIfNeeded();
notifyTransformedContentsSizeChanged();
return;
}
bool performedZoom = false;
bool shouldZoom = !m_userPerformedManualZoom;
if (m_mainFrame && m_mainFrame->loader() && isBackForwardLoadType(m_mainFrame->loader()->loadType()))
shouldZoom = false;
if (shouldZoom && shouldZoomToInitialScaleOnLoad()) {
FloatPoint anchor = centerOfVisibleContentsRect();
if (!scrollPosition().x())
anchor.setX(0);
if (!scrollPosition().y())
anchor.setY(0);
performedZoom = zoomAboutPoint(initialScale(), anchor);
}
layoutIfNeeded();
if (!performedZoom) {
notifyTransformedContentsSizeChanged();
}
}
double WebPagePrivate::zoomToFitScale() const
{
int contentWidth = contentsSize().width();
Document* doc = m_page->mainFrame()->document();
bool isImageDocument = doc && doc->isImageDocument();
if (isImageDocument)
contentWidth = static_cast<ImageDocument*>(doc)->imageSize().width();
double zoomToFitScale = contentWidth > 0.0 ? static_cast<double>(m_actualVisibleWidth) / contentWidth : 1.0;
int contentHeight = contentsSize().height();
if (contentHeight * zoomToFitScale < static_cast<double>(m_defaultLayoutSize.height()))
zoomToFitScale = contentHeight > 0 ? static_cast<double>(m_defaultLayoutSize.height()) / contentHeight : 1.0;
zoomToFitScale = std::max(zoomToFitScale, minimumZoomToFitScale);
if (!isImageDocument)
return zoomToFitScale;
return std::min(zoomToFitScale, maximumImageDocumentZoomToFitScale);
}
bool WebPagePrivate::respectViewport() const
{
return m_forceRespectViewportArguments || contentsSize().width() <= m_virtualViewportSize.width() + 1;
}
double WebPagePrivate::initialScale() const
{
if (m_initialScale > 0.0 && respectViewport())
return m_initialScale;
if (m_webSettings->isZoomToFitOnLoad())
return zoomToFitScale();
return 1.0;
}
double WebPage::initialScale() const
{
return d->initialScale();
}
void WebPage::initializeIconDataBase()
{
IconDatabaseClientBlackBerry::instance()->initIconDatabase(d->m_webSettings);
}
bool WebPage::isUserScalable() const
{
return d->isUserScalable();
}
void WebPage::setUserScalable(bool userScalable)
{
d->setUserScalable(userScalable);
}
double WebPage::currentScale() const
{
return d->currentScale();
}
void WebPage::setInitialScale(double initialScale)
{
d->setInitialScale(initialScale);
}
double WebPage::minimumScale() const
{
return d->minimumScale();
}
void WebPage::setMinimumScale(double minimumScale)
{
d->setMinimumScale(minimumScale);
}
void WebPage::setMaximumScale(double maximumScale)
{
d->setMaximumScale(maximumScale);
}
double WebPagePrivate::maximumScale() const
{
double zoomToFitScale = this->zoomToFitScale();
if (m_maximumScale >= m_minimumScale && respectViewport())
return std::max(zoomToFitScale, m_maximumScale);
return hasVirtualViewport() ? std::max<double>(zoomToFitScale, 4.0) : 4.0;
}
double WebPage::maximumScale() const
{
return d->maximumScale();
}
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;
m_client->scaleChanged();
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);
}
Platform::ViewportAccessor* WebPage::webkitThreadViewportAccessor() const
{
return d->m_webkitThreadViewportAccessor;
}
Platform::IntSize WebPage::viewportSize() const
{
return d->transformedActualVisibleSize();
}
IntSize WebPagePrivate::transformedViewportSize() const
{
return BlackBerry::Platform::Settings::instance()->applicationSize();
}
void WebPagePrivate::notifyTransformChanged()
{
notifyTransformedContentsSizeChanged();
notifyTransformedScrollChanged();
m_backingStore->d->transformChanged();
}
void WebPagePrivate::notifyTransformedContentsSizeChanged()
{
m_previousContentsSize = contentsSize();
const IntSize size = m_webkitThreadViewportAccessor->pixelContentsSize();
m_backingStore->d->contentsSizeChanged(size);
m_client->contentsSizeChanged();
}
void WebPagePrivate::notifyTransformedScrollChanged()
{
const IntPoint pos = transformedScrollPosition();
m_backingStore->d->scrollChanged(pos);
m_client->scrollChanged();
#if ENABLE(FULLSCREEN_API)
adjustFullScreenElementDimensionsIfNeeded();
#endif
}
bool WebPagePrivate::setViewMode(ViewMode mode)
{
if (!m_mainFrame || !m_mainFrame->view())
return false;
m_viewMode = mode;
bool snapToIncrement = didLayoutExceedMaximumIterations();
IntSize currentSize = m_mainFrame->view()->fixedLayoutSize();
IntSize newSize = fixedLayoutSize(snapToIncrement);
if (currentSize == newSize)
return false;
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; }
int WebPagePrivate::playerID() const
{
return m_client ? m_client->getInstanceId() : 0;
}
void WebPagePrivate::setCursor(PlatformCursor handle)
{
if (m_currentCursor.type() != handle.type()) {
m_currentCursor = handle;
m_client->cursorChanged(handle.type(), handle.url().c_str(), handle.hotspot());
}
}
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(); }
void WebPagePrivate::showVirtualKeyboard(bool showKeyboard)
{
m_client->showVirtualKeyboard(showKeyboard);
}
void WebPagePrivate::ensureContentVisible(bool centerInView)
{
m_inputHandler->ensureFocusElementVisible(centerInView);
}
void WebPagePrivate::zoomToContentRect(const IntRect& rect)
{
if (!isUserScalable())
return;
FloatPoint anchor = FloatPoint(rect.width() / 2.0 + rect.x(), rect.height() / 2.0 + rect.y());
IntSize viewSize = viewportSize();
double scaleH = (double)viewSize.width() / (double)rect.width();
double scaleV = (double)viewSize.height() / (double)rect.height();
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*, const char*)
{
return m_client->shouldPluginEnterFullScreen();
}
void WebPagePrivate::didPluginEnterFullScreen(PluginView* plugin, const char* windowUniquePrefix)
{
m_fullScreenPluginView = plugin;
m_client->didPluginEnterFullScreen();
if (!m_client->window())
return;
Platform::Graphics::Window::setTransparencyDiscardFilter(windowUniquePrefix);
m_client->window()->setSensitivityFullscreenOverride(true);
}
void WebPagePrivate::didPluginExitFullScreen(PluginView*, const char*)
{
m_fullScreenPluginView = 0;
m_client->didPluginExitFullScreen();
if (!m_client->window())
return;
Platform::Graphics::Window::setTransparencyDiscardFilter(0);
m_client->window()->setSensitivityFullscreenOverride(false);
}
void WebPagePrivate::onPluginStartBackgroundPlay(PluginView*, const char*)
{
m_client->onPluginStartBackgroundPlay();
}
void WebPagePrivate::onPluginStopBackgroundPlay(PluginView*, const char*)
{
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.
#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();
}
void WebPagePrivate::authenticationChallenge(const KURL& url, const ProtectionSpace& protectionSpace, const Credential& inputCredential)
{
AuthenticationChallengeManager* authmgr = AuthenticationChallengeManager::instance();
BlackBerry::Platform::String username;
BlackBerry::Platform::String password;
BlackBerry::Platform::String requestURL(url.string());
#if !defined(PUBLIC_BUILD) || !PUBLIC_BUILD
if (m_dumpRenderTree) {
Credential credential(inputCredential, inputCredential.persistence());
if (m_dumpRenderTree->didReceiveAuthenticationChallenge(credential))
authmgr->notifyChallengeResult(url, protectionSpace, AuthenticationChallengeSuccess, credential);
else
authmgr->notifyChallengeResult(url, protectionSpace, AuthenticationChallengeCancelled, inputCredential);
return;
}
#endif
#if ENABLE(BLACKBERRY_CREDENTIAL_PERSIST)
if (m_webSettings->isCredentialAutofillEnabled() && !m_webSettings->isPrivateBrowsingEnabled())
credentialManager().autofillAuthenticationChallenge(protectionSpace, username, password);
#endif
bool isConfirmed = m_client->authenticationChallenge(protectionSpace.realm().characters(), protectionSpace.realm().length(), username, password, requestURL, protectionSpace.isProxy());
#if ENABLE(BLACKBERRY_CREDENTIAL_PERSIST)
Credential credential(username, password, CredentialPersistencePermanent);
if (m_webSettings->isCredentialAutofillEnabled() && !m_webSettings->isPrivateBrowsingEnabled() && isConfirmed)
credentialManager().saveCredentialIfConfirmed(this, CredentialTransformData(protectionSpace, credential));
#else
Credential credential(username, password, CredentialPersistenceNone);
#endif
if (isConfirmed)
authmgr->notifyChallengeResult(url, protectionSpace, AuthenticationChallengeSuccess, credential);
else
authmgr->notifyChallengeResult(url, protectionSpace, AuthenticationChallengeCancelled, inputCredential);
}
PageClientBlackBerry::SaveCredentialType WebPagePrivate::notifyShouldSaveCredential(bool isNew)
{
return static_cast<PageClientBlackBerry::SaveCredentialType>(m_client->notifyShouldSaveCredential(isNew));
}
void WebPagePrivate::syncProxyCredential(const WebCore::Credential& credential)
{
m_client->syncProxyCredential(credential.user(), credential.password());
}
void WebPagePrivate::notifyPopupAutofillDialog(const Vector<String>& candidates)
{
vector<BlackBerry::Platform::String> textItems;
for (size_t i = 0; i < candidates.size(); i++)
textItems.push_back(candidates[i]);
m_client->notifyPopupAutofillDialog(textItems);
}
void WebPagePrivate::notifyDismissAutofillDialog()
{
m_client->notifyDismissAutofillDialog();
}
bool WebPagePrivate::useFixedLayout() const
{
return true;
}
Platform::WebContext WebPagePrivate::webContext(TargetDetectionStrategy strategy)
{
Platform::WebContext context;
RefPtr<Node> node = contextNode(strategy);
m_currentContextNode = node;
if (!m_currentContextNode)
return context;
PlatformMouseEvent mouseEvent(IntPoint(), IntPoint(), PlatformEvent::MouseMoved, 0, NoButton, false, false, false, TouchScreen);
if (!m_currentContextNode->dispatchMouseEvent(mouseEvent, eventNames().contextmenuEvent, 0)) {
context.setFlag(Platform::WebContext::IsOnContextMenuPrevented);
return context;
}
layoutIfNeeded();
bool nodeAllowSelectionOverride = false;
bool nodeIsImage = node->isHTMLElement() && node->hasTagName(HTMLNames::imgTag);
Node* linkNode = node->enclosingLinkEventParentOrSelf();
if (linkNode && (node == linkNode || node->isTextNode() || nodeIsImage)) {
KURL href;
if (linkNode->isLink() && linkNode->hasAttributes()) {
if (const Attribute* attribute = toElement(linkNode)->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());
if (linkNode->parentNode() && linkNode->parentNode()->canStartSelection())
nodeAllowSelectionOverride = true;
}
}
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);
if (CachedImage* cachedImage = imageElement->cachedImage()) {
if (cachedImage->isLoaded() && cachedImage->resourceBuffer()) {
String url = stripLeadingAndTrailingHTMLSpaces(imageElement->getAttribute(HTMLNames::srcAttr).string());
context.setSrc(node->document()->completeURL(url).string());
String mimeType = cachedImage->response().mimeType();
if (mimeType.isEmpty()) {
StringBuilder builder;
String extension = cachedImage->image()->filenameExtension();
builder.append("image/");
if (extension.isEmpty())
builder.append("unknown");
else if (extension == "jpg")
builder.append("jpeg");
else
builder.append(extension);
mimeType = builder.toString();
}
context.setMimeType(mimeType);
}
}
String alt = imageElement->altText();
if (!alt.isNull())
context.setAlt(alt);
}
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());
}
}
if (node->isTextNode()) {
Text* curText = toText(node.get());
if (!curText->wholeText().isEmpty())
context.setText(curText->wholeText());
}
bool canStartSelection = node->canStartSelection();
if (node->isElementNode()) {
Element* element = toElement(node->deprecatedShadowAncestorNode());
if (DOMSupport::isTextBasedContentEditableElement(element)) {
if (!canStartSelection) {
Node* nodeUnderFinger = m_touchEventHandler->lastFatFingersResult().isValid() ? m_touchEventHandler->lastFatFingersResult().node(FatFingersResult::ShadowContentAllowed) : 0;
if (nodeUnderFinger)
canStartSelection = nodeUnderFinger->canStartSelection();
}
context.setFlag(Platform::WebContext::IsInput);
if (element->hasTagName(HTMLNames::inputTag))
context.setFlag(Platform::WebContext::IsSingleLine);
if (DOMSupport::isPasswordElement(element))
context.setFlag(Platform::WebContext::IsPassword);
String elementText(DOMSupport::inputElementText(element));
if (!elementText.stripWhiteSpace().isEmpty())
context.setText(elementText);
else if (!node->focused() && m_touchEventHandler->lastFatFingersResult().isValid() && strategy == RectBased) {
m_touchEventHandler->sendClickAtFatFingersPoint();
}
}
}
if (!nodeAllowSelectionOverride && !canStartSelection)
context.resetFlag(Platform::WebContext::IsSelectable);
if (node->isFocusable())
context.setFlag(Platform::WebContext::IsFocusable);
while (node) {
if (node->isElementNode()) {
Element* element = toElement(node->deprecatedShadowAncestorNode());
String webWorksContext(DOMSupport::webWorksContext(element));
if (!webWorksContext.stripWhiteSpace().isEmpty()) {
context.setFlag(Platform::WebContext::IsWebWorksContext);
context.setWebWorksContext(webWorksContext);
break;
}
}
node = node->parentNode();
}
return context;
}
Platform::WebContext WebPage::webContext(TargetDetectionStrategy strategy) const
{
return d->webContext(strategy);
}
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;
unsigned modifiers = m_lastMouseEvent.shiftKey() ? 0 : KEYMOD_SHIFT |
m_lastMouseEvent.ctrlKey() ? 0 : KEYMOD_CTRL |
m_lastMouseEvent.altKey() ? 0 : KEYMOD_ALT;
const Platform::ViewportAccessor* viewportAccessor = m_webkitThreadViewportAccessor;
BlackBerry::Platform::MouseEvent event(buttonMask, buttonMask,
viewportAccessor->roundToPixelFromDocumentContents(WebCore::FloatPoint(m_lastMouseEvent.position())),
viewportAccessor->roundToPixelFromDocumentContents(WebCore::FloatPoint(m_lastMouseEvent.globalPosition())),
0, modifiers, 0);
event.populateDocumentPosition(m_lastMouseEvent.position(), viewportAccessor->documentContentsFromViewport(m_lastMouseEvent.position()));
m_webPage->mouseEvent(event);
}
IntSize WebPagePrivate::fixedLayoutSize(bool snapToIncrement) const
{
if (hasVirtualViewport())
return m_virtualViewportSize;
const int defaultLayoutWidth = m_defaultLayoutSize.width();
const int defaultLayoutHeight = m_defaultLayoutSize.height();
int minWidth = defaultLayoutWidth;
int maxWidth = DEFAULT_MAX_LAYOUT_WIDTH;
int maxHeight = DEFAULT_MAX_LAYOUT_HEIGHT;
if (m_loadState == None || m_loadState == Provisional)
return IntSize(defaultLayoutWidth, defaultLayoutHeight);
if (m_viewMode == FixedDesktop) {
int width = maxWidth;
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) {
int width = std::max(absoluteVisibleOverflowSize().width(), contentsSize().width());
if (m_pendingOrientation != -1 && !m_nestedLayoutFinishedCount && !m_overflowExceedsContentsSize)
width = 0;
if (snapToIncrement) {
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);
}
ASSERT_NOT_REACHED();
return IntSize(defaultLayoutWidth, defaultLayoutHeight);
}
BackingStoreClient* WebPagePrivate::backingStoreClient() const
{
return m_backingStoreClient;
}
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_inRegionScroller->d->isActive())
m_inRegionScroller->d->clearDocumentData(documentGoingAway);
if (documentGoingAway->frame())
m_inputHandler->frameUnloaded(documentGoingAway->frame());
Node* nodeUnderFatFinger = m_touchEventHandler->lastFatFingersResult().node();
if (nodeUnderFatFinger && nodeUnderFatFinger->document() == documentGoingAway)
m_touchEventHandler->resetLastFatFingersResult();
}
typedef bool (*PredicateFunction)(RenderLayer*);
static bool isPositionedContainer(RenderLayer* layer)
{
RenderObject* o = layer->renderer();
return o->isRenderView() || o->isOutOfFlowPositioned() || o->isRelPositioned() || layer->hasTransform();
}
static bool isFixedPositionedContainer(RenderLayer* layer)
{
RenderObject* o = layer->renderer();
return o->isRenderView() || (o->isOutOfFlowPositioned() && 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 = toFrameView(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);
if (noClipOfMainFrame && view == m_mainFrame->view()) {
ASSERT_NOT_REACHED();
return IntRect(IntPoint::zero(), view->contentsSize());
}
IntRect visibleWindowRect(view->contentsToWindow(view->visibleContentRect()));
if (view->parent() && !(noClipOfMainFrame && view->parent() == m_mainFrame->view())) {
visibleWindowRect.intersect(getRecursiveVisibleWindowRect(view->parent(), noClipOfMainFrame));
}
return visibleWindowRect;
}
void WebPagePrivate::assignFocus(Platform::FocusDirection direction)
{
ASSERT((int) Platform::FocusDirectionNone == (int) FocusDirectionNone);
ASSERT((int) Platform::FocusDirectionForward == (int) FocusDirectionForward);
ASSERT((int) Platform::FocusDirectionBackward == (int) FocusDirectionBackward);
clearFocusNode();
switch (direction) {
case FocusDirectionForward:
case FocusDirectionBackward:
m_page->focusController()->setInitialFocus((FocusDirection) direction, 0);
break;
case FocusDirectionNone:
break;
default:
ASSERT_NOT_REACHED();
}
}
void WebPage::assignFocus(Platform::FocusDirection direction)
{
if (d->m_page->defersLoading())
return;
d->assignFocus(direction);
}
void WebPage::focusNextField()
{
d->m_inputHandler->focusNextField();
}
void WebPage::focusPreviousField()
{
d->m_inputHandler->focusPreviousField();
}
void WebPage::submitForm()
{
d->m_inputHandler->submitForm();
}
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();
const Platform::ViewportAccessor* viewportAccessor = m_webkitThreadViewportAccessor;
IntRect focusRect = rectForNode(doc->focusedElement());
focusRect = adjustRectOffsetForFrameOffset(focusRect, doc->focusedElement());
focusRect = viewportAccessor->roundToPixelFromDocumentContents(WebCore::FloatRect(focusRect));
focusRect.intersect(viewportAccessor->pixelContentsRect());
return focusRect;
}
PassRefPtr<Node> WebPagePrivate::contextNode(TargetDetectionStrategy strategy)
{
EventHandler* eventHandler = focusedOrMainFrame()->eventHandler();
const FatFingersResult lastFatFingersResult = m_touchEventHandler->lastFatFingersResult();
bool isTouching = lastFatFingersResult.isValid() && strategy == RectBased;
if (m_webSettings->doesGetFocusNodeContext() && !isTouching) {
RefPtr<Node> node;
node = m_page->focusController()->focusedOrMainFrame()->document()->focusedElement();
if (node) {
IntRect visibleRect = IntRect(IntPoint(), actualVisibleSize());
if (!visibleRect.intersects(getNodeWindowRect(node.get())))
return 0;
}
return node.release();
}
if (isTouching && lastFatFingersResult.isTextInput())
return lastFatFingersResult.node(FatFingersResult::ShadowContentNotAllowed);
if (strategy == RectBased) {
FatFingersResult result = FatFingers(this, lastFatFingersResult.adjustedPosition(), FatFingers::Text).findBestPoint();
m_touchEventHandler->cacheTextResult(result);
return result.node(FatFingersResult::ShadowContentNotAllowed);
}
if (strategy == FocusBased)
return m_inputHandler->currentFocusElement();
IntPoint contentPos;
if (isTouching)
contentPos = lastFatFingersResult.adjustedPosition();
else
contentPos = m_webkitThreadViewportAccessor->documentContentsFromViewport(m_lastMouseEvent.position());
HitTestResult result = eventHandler->hitTestResultAtPoint(contentPos);
return result.innerNode();
}
static inline int distanceBetweenPoints(IntPoint p1, IntPoint p2)
{
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& documentPoint)
{
IntRect clickRect(documentPoint.x() - blockClickRadius, documentPoint.y() - blockClickRadius, 2 * blockClickRadius, 2 * blockClickRadius);
Node* originalNode = nodeForZoomUnderPoint(documentPoint);
if (!originalNode)
return 0;
Node* node = bestChildNodeForClickRect(originalNode, clickRect);
return node ? adjustedBlockZoomNodeForZoomAndExpandingRatioLimits(node) : adjustedBlockZoomNodeForZoomAndExpandingRatioLimits(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& documentPoint)
{
if (!m_mainFrame)
return 0;
HitTestResult result = m_mainFrame->eventHandler()->hitTestResultAtPoint(documentPoint);
Node* node = result.innerNonSharedNode();
if (!node)
return 0;
RenderObject* renderer = node->renderer();
while (!renderer) {
node = node->parentNode();
renderer = node->renderer();
}
return node;
}
Node* WebPagePrivate::adjustedBlockZoomNodeForZoomAndExpandingRatioLimits(Node* node)
{
Node* initialNode = node;
RenderObject* renderer = node->renderer();
bool acceptableNodeSize = newScaleForBlockZoomRect(rectForNode(node), 1.0, 0) < maxBlockZoomScale();
IntSize actualVisibleSize = this->actualVisibleSize();
while (!renderer || !acceptableNodeSize) {
node = node->parentNode();
IntRect nodeRect = rectForNode(node);
if (!node || static_cast<double>(actualVisibleSize.width() - nodeRect.width()) / actualVisibleSize.width() < minimumExpandingRatio)
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();
IntRect blockRect;
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().toInt();
yOffset += renderBlock->y().toInt();
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 = IntRect(renderer->absoluteClippedOverflowRect());
if (renderer->isText()) {
RenderBlock* rb = renderer->containingBlock();
int blockWidth = 0;
int lineCount = rb->lineCount();
for (int i = 0; i < lineCount; i++)
blockWidth = max(blockWidth, rb->availableLogicalWidthForLine(i, false).toInt());
blockRect.setWidth(blockWidth);
blockRect.setX(blockRect.x() + rb->logicalLeftOffsetForLine(1, false));
}
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);
if (!mainFrame())
return IntPoint();
return mainFrame()->view()->windowToContents(frame->view()->contentsToWindow(IntPoint::zero()));
}
IntRect WebPagePrivate::adjustRectOffsetForFrameOffset(const IntRect& rect, const Node* node)
{
if (!node)
return rect;
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>(pageArea - 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();
if (static_cast<double>(pageArea - tempBlockArea) / pageArea < minimumExpandingRatio)
break;
if (tRect.isEmpty())
continue; if (tempBlockArea < 1.1 * originalArea)
continue; IntSize actualSize = actualVisibleSize();
if (static_cast<double>(actualSize.width() - tRect.width()) / actualSize.width() < minimumExpandingRatio)
break;
if (tempBlockArea < blockExpansionRatio * originalArea) {
blockRect = tRect;
m_currentBlockZoomAdjustedNode = tnode;
} else
break;
}
}
const Platform::ViewportAccessor* viewportAccessor = m_webkitThreadViewportAccessor;
blockRect = adjustRectOffsetForFrameOffset(blockRect, node);
blockRect = viewportAccessor->roundToPixelFromDocumentContents(WebCore::FloatRect(blockRect));
blockRect.intersect(viewportAccessor->pixelContentsRect());
return blockRect;
}
void WebPagePrivate::zoomAnimationFinished(double finalAnimationScale, const WebCore::FloatPoint& finalAnimationDocumentScrollPosition, bool shouldConstrainScrollingToContentEdge)
{
if (!m_mainFrame)
return;
const Platform::ViewportAccessor* viewportAccessor = m_webkitThreadViewportAccessor;
IntPoint anchor(viewportAccessor->roundedDocumentContents(finalAnimationDocumentScrollPosition));
bool willUseTextReflow = false;
#if ENABLE(VIEWPORT_REFLOW)
willUseTextReflow = m_webPage->settings()->textReflowMode() != WebSettings::TextReflowDisabled;
toggleTextReflowIfEnabledForBlockZoomOnly(m_shouldReflowBlock);
setNeedsLayout();
#endif
TransformationMatrix zoom;
zoom.scale(finalAnimationScale);
*m_transformationMatrix = zoom;
m_backingStore->d->suspendBackingStoreUpdates();
m_backingStore->d->suspendScreenUpdates();
updateViewportSize();
FrameView* mainFrameView = m_mainFrame->view();
bool constrainsScrollingToContentEdge = true;
if (mainFrameView) {
constrainsScrollingToContentEdge = mainFrameView->constrainsScrollingToContentEdge();
mainFrameView->setConstrainsScrollingToContentEdge(shouldConstrainScrollingToContentEdge);
}
#if ENABLE(VIEWPORT_REFLOW)
layoutIfNeeded();
if (willUseTextReflow && m_shouldReflowBlock) {
Platform::IntPoint roundedReflowOffset(
std::floorf(m_finalAnimationDocumentScrollPositionReflowOffset.x()),
std::floorf(m_finalAnimationDocumentScrollPositionReflowOffset.y()));
IntRect reflowedRect = rectForNode(m_currentBlockZoomAdjustedNode.get());
reflowedRect = adjustRectOffsetForFrameOffset(reflowedRect, m_currentBlockZoomAdjustedNode.get());
reflowedRect.move(roundedReflowOffset.x(), roundedReflowOffset.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 TASTART:
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_finalAnimationDocumentScrollPositionReflowOffset.y()));
resetBlockZoom();
}
#endif
if (!willUseTextReflow) {
setScrollPosition(anchor);
if (!m_shouldReflowBlock)
resetBlockZoom();
}
notifyTransformChanged();
m_client->scaleChanged();
if (mainFrameView)
mainFrameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdge);
m_backingStore->d->resumeBackingStoreUpdates();
m_backingStore->d->resumeScreenUpdates(BackingStore::RenderAndBlit);
}
void WebPage::zoomAnimationFinished(double finalScale, const Platform::FloatPoint& finalDocumentScrollPosition, bool shouldConstrainScrollingToContentEdge)
{
d->zoomAnimationFinished(finalScale, finalDocumentScrollPosition, shouldConstrainScrollingToContentEdge);
}
void WebPage::resetBlockZoom()
{
d->resetBlockZoom();
}
void WebPagePrivate::resetBlockZoom()
{
m_currentBlockZoomNode = 0;
m_currentBlockZoomAdjustedNode = 0;
m_shouldReflowBlock = false;
}
void WebPage::destroyWebPageCompositor()
{
#if USE(ACCELERATED_COMPOSITING)
d->syncDestroyCompositorOnCompositingThread();
#endif
}
void WebPage::destroy()
{
disableWebInspector();
d->m_backingStore->d->suspendBackingStoreUpdates();
d->m_backingStore->d->suspendScreenUpdates();
d->m_page->backForward()->close();
FrameLoader* loader = d->m_mainFrame->loader();
d->m_mainFrame = 0;
if (loader)
loader->detachFromParent();
deleteGuardedObject(this);
}
WebPageClient* WebPage::client() const
{
return d->m_client;
}
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_userPerformedManualZoom = false;
d->m_userPerformedManualScroll = false;
d->m_backingStore->d->suspendScreenUpdates();
d->m_page->goBackOrForward(delta);
d->m_backingStore->d->resumeScreenUpdates(BackingStore::None);
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( true);
}
void WebPage::reloadFromCache()
{
d->m_mainFrame->loader()->reload( false);
}
WebSettings* WebPage::settings() const
{
return d->m_webSettings;
}
WebCookieJar* WebPage::cookieJar() const
{
if (!d->m_cookieJar)
d->m_cookieJar = new WebCookieJar();
return d->m_cookieJar;
}
bool WebPage::isLoading() const
{
return d->isLoading();
}
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)
{
if (visible != m_visible) {
if (visible) {
if (m_mainFrame)
m_mainFrame->animation()->resumeAnimations();
if (m_page->scriptedAnimationsSuspended())
m_page->resumeScriptedAnimations();
} else {
if (m_mainFrame)
m_mainFrame->animation()->suspendAnimations();
if (!m_page->scriptedAnimationsSuspended())
m_page->suspendScriptedAnimations();
closePagePopup();
}
m_visible = visible;
m_backingStore->d->updateSuspendScreenUpdateState();
}
#if ENABLE(PAGE_VISIBILITY_API)
setPageVisibilityState();
#endif
}
void WebPage::setVisible(bool visible)
{
if (d->m_visible == visible)
return;
d->setVisible(visible);
AuthenticationChallengeManager::instance()->pageVisibilityChanged(d, visible);
if (!visible) {
d->suspendBackingStore();
size_t foundIndex = visibleWebPages()->find(this);
if (foundIndex != WTF::notFound)
visibleWebPages()->remove(foundIndex);
if (BackingStorePrivate::currentBackingStoreOwner() == this && !visibleWebPages()->isEmpty())
visibleWebPages()->last()->d->resumeBackingStore();
#if USE(ACCELERATED_COMPOSITING)
d->suspendRootLayerCommit();
#endif
return;
}
#if USE(ACCELERATED_COMPOSITING)
d->resumeRootLayerCommit();
#endif
if (d->m_backingStore->d->isOpenGLCompositing() && !d->m_webSettings->isBackingStoreEnabled()) {
d->setCompositorDrawsRootLayer(true);
#if USE(ACCELERATED_COMPOSITING)
d->setNeedsOneShotDrawingSynchronization();
#endif
d->setShouldResetTilesWhenShown(true);
return;
}
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();
d->resumeBackingStore();
}
void WebPagePrivate::selectionChanged(Frame* frame)
{
m_inputHandler->selectionChanged();
m_page->focusController()->setFocusedFrame(frame);
}
void WebPagePrivate::updateSelectionScrollView(const Node* node)
{
m_inRegionScroller->d->updateSelectionScrollView(node);
}
void WebPagePrivate::updateDelegatedOverlays(bool dispatched)
{
if (dispatched)
m_updateDelegatedOverlaysDispatched = false;
else if (m_updateDelegatedOverlaysDispatched) {
return;
}
if (Platform::webKitThreadMessageClient()->isCurrentThread()) {
if (m_selectionHandler->isSelectionActive())
m_selectionHandler->selectionPositionChanged();
if (m_inspectorOverlay)
m_inspectorOverlay->update();
} else if (m_selectionHandler->isSelectionActive()) {
m_updateDelegatedOverlaysDispatched = true;
Platform::webKitThreadMessageClient()->dispatchMessage(Platform::createMethodCallMessage(&WebPagePrivate::updateDelegatedOverlays, this, true ));
}
}
void WebPage::setCaretHighlightStyle(Platform::CaretHighlightStyle)
{
}
bool WebPage::setBatchEditingActive(bool active)
{
return d->m_inputHandler->setBatchEditingActive(active);
}
bool WebPage::setInputSelection(unsigned start, unsigned end)
{
if (d->m_page->defersLoading())
return false;
return d->m_inputHandler->setSelection(start, end);
}
int WebPage::inputCaretPosition() const
{
return d->m_inputHandler->caretPosition();
}
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, BlackBerry::Platform::String value)
: DeferredTaskType(webPagePrivate)
{
webPagePrivate->m_cachedDateTimeInput = value;
}
private:
virtual void performInternal(WebPagePrivate* webPagePrivate)
{
webPagePrivate->m_webPage->setDateTimeInput(webPagePrivate->m_cachedDateTimeInput);
}
};
void WebPage::setDateTimeInput(const BlackBerry::Platform::String& value)
{
if (d->m_page->defersLoading()) {
d->m_deferredTasks.append(adoptPtr(new DeferredTaskSetDateTimeInput(d, value)));
return;
}
DeferredTaskSetDateTimeInput::finishOrCancel(d);
d->m_inputHandler->setInputValue(value);
}
class DeferredTaskSetColorInput: public DeferredTask<&WebPagePrivate::m_wouldSetColorInput> {
public:
explicit DeferredTaskSetColorInput(WebPagePrivate* webPagePrivate, BlackBerry::Platform::String value)
: DeferredTaskType(webPagePrivate)
{
webPagePrivate->m_cachedColorInput = value;
}
private:
virtual void performInternal(WebPagePrivate* webPagePrivate)
{
webPagePrivate->m_webPage->setColorInput(webPagePrivate->m_cachedColorInput);
}
};
void WebPage::setColorInput(const BlackBerry::Platform::String& value)
{
if (d->m_page->defersLoading()) {
d->m_deferredTasks.append(adoptPtr(new DeferredTaskSetColorInput(d, value)));
return;
}
DeferredTaskSetColorInput::finishOrCancel(d);
d->m_inputHandler->setInputValue(value);
}
void WebPage::setVirtualViewportSize(const Platform::IntSize& size)
{
d->m_virtualViewportSize = WebCore::IntSize(size);
}
void WebPage::resetVirtualViewportOnCommitted(bool reset)
{
d->m_resetVirtualViewportOnCommitted = reset;
}
Platform::IntSize WebPagePrivate::recomputeVirtualViewportFromViewportArguments()
{
static const ViewportArguments defaultViewportArguments;
if (m_viewportArguments == defaultViewportArguments)
return IntSize();
int desktopWidth = DEFAULT_MAX_LAYOUT_WIDTH;
int deviceWidth = Platform::Graphics::Screen::primaryScreen()->width();
int deviceHeight = Platform::Graphics::Screen::primaryScreen()->height();
float devicePixelRatio = m_webSettings->devicePixelRatio();
ViewportAttributes result = computeViewportAttributes(m_viewportArguments, desktopWidth, deviceWidth, deviceHeight, devicePixelRatio, m_defaultLayoutSize);
m_page->setDeviceScaleFactor(devicePixelRatio);
setUserScalable(m_webSettings->isUserScalable() && result.userScalable);
if (result.initialScale > 0)
setInitialScale(result.initialScale * devicePixelRatio);
if (result.minimumScale > 0)
setMinimumScale(result.minimumScale * devicePixelRatio);
if (result.maximumScale > 0)
setMaximumScale(result.maximumScale * devicePixelRatio);
return Platform::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)
{
if (arguments == m_viewportArguments)
return;
static const ViewportArguments defaultViewportArguments;
if (arguments == defaultViewportArguments) {
m_viewportArguments = m_userViewportArguments;
m_forceRespectViewportArguments = m_userViewportArguments != defaultViewportArguments;
} else
m_viewportArguments = arguments;
if (!m_viewportArguments.width)
m_viewportArguments.width = ViewportArguments::ValueDeviceWidth;
if (!m_viewportArguments.height)
m_viewportArguments.height = ViewportArguments::ValueDeviceHeight;
Platform::IntSize virtualViewport = recomputeVirtualViewportFromViewportArguments();
m_webPage->setVirtualViewportSize(virtualViewport);
bool isLoadFinished = loadState() == Finished;
if (isLoadFinished) {
m_userPerformedManualZoom = false;
setShouldZoomToInitialScaleAfterLoadFinished(true);
}
if (loadState() == Committed || isLoadFinished)
zoomToInitialScaleOnLoad();
}
void WebPagePrivate::suspendBackingStore()
{
#if USE(ACCELERATED_COMPOSITING)
if (m_backingStore->d->isOpenGLCompositing()) {
if (m_visible)
setCompositorDrawsRootLayer(true);
return;
}
#endif
}
void WebPagePrivate::resumeBackingStore()
{
ASSERT(m_webPage->isVisible());
if (!m_backingStore->d->isActive() || shouldResetTilesWhenShown()) {
BackingStorePrivate::setCurrentBackingStoreOwner(m_webPage);
if (m_backingStore->d->isOpenGLCompositing())
setCompositorDrawsRootLayer(!m_backingStore->d->isActive());
m_backingStore->d->orientationChanged(); m_backingStore->d->resetTiles();
m_backingStore->d->updateTiles(false , false );
#if USE(ACCELERATED_COMPOSITING)
setNeedsOneShotDrawingSynchronization();
#endif
m_backingStore->d->renderAndBlitVisibleContentsImmediately();
} else {
if (m_backingStore->d->isOpenGLCompositing())
setCompositorDrawsRootLayer(false);
m_backingStore->d->updateTiles(true , false );
#if USE(ACCELERATED_COMPOSITING)
setNeedsOneShotDrawingSynchronization();
#endif
}
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
}
void WebPage::setScreenOrientation(int orientation)
{
d->m_pendingOrientation = orientation;
}
void WebPage::applyPendingOrientationIfNeeded()
{
if (d->m_pendingOrientation != -1)
d->setScreenOrientation(d->m_pendingOrientation);
d->m_inputHandler->redrawSpellCheckDialogIfRequired(false );
}
bool WebPagePrivate::setViewportSize(const IntSize& transformedActualVisibleSize, const IntSize& defaultLayoutSize, bool ensureFocusElementVisible)
{
if (m_pendingOrientation == -1 && transformedActualVisibleSize == this->transformedActualVisibleSize())
return false;
BackingStore::ResumeUpdateOperation screenResumeOperation = BackingStore::Blit;
m_backingStore->d->suspendScreenUpdates();
m_backingStore->d->suspendBackingStoreUpdates();
if (!m_visible || !m_backingStore->d->isActive())
setShouldResetTilesWhenShown(true);
bool hasPendingOrientation = m_pendingOrientation != -1;
IntSize viewportSizeBefore = actualVisibleSize();
FloatPoint centerOfVisibleContentsRect = this->centerOfVisibleContentsRect();
bool newVisibleRectContainsOldVisibleRect = (m_actualVisibleHeight <= transformedActualVisibleSize.height())
&& (m_actualVisibleWidth <= transformedActualVisibleSize.width());
bool atInitialScale = m_webPage->isAtInitialZoom();
bool atTop = !scrollPosition().y();
bool atLeft = !scrollPosition().x();
setDefaultLayoutSize(defaultLayoutSize);
bool needsLayout = false;
Platform::IntSize newVirtualViewport = recomputeVirtualViewportFromViewportArguments();
if (!newVirtualViewport.isEmpty()) {
m_webPage->setVirtualViewportSize(newVirtualViewport);
m_mainFrame->view()->setUseFixedLayout(useFixedLayout());
m_mainFrame->view()->setFixedLayoutSize(fixedLayoutSize());
needsLayout = true;
}
m_actualVisibleWidth = transformedActualVisibleSize.width();
m_actualVisibleHeight = transformedActualVisibleSize.height();
IntSize viewportSizeAfter = actualVisibleSize();
IntSize offset;
if (hasPendingOrientation && !m_fullscreenNode) {
offset = IntSize(roundf((viewportSizeBefore.width() - viewportSizeAfter.width()) / 2.0),
roundf((viewportSizeBefore.height() - viewportSizeAfter.height()) / 2.0));
}
if (atTop)
offset.setHeight(0);
if (atLeft)
offset.setWidth(0);
IntPoint bottomRight(
scrollPosition().x() + viewportSizeAfter.width(),
scrollPosition().y() + viewportSizeAfter.height());
if (bottomRight.x() + offset.width() > contentsSize().width())
offset.setWidth(contentsSize().width() - bottomRight.x());
if (bottomRight.y() + offset.height() > contentsSize().height())
offset.setHeight(contentsSize().height() - bottomRight.y());
if (scrollPosition().x() + offset.width() < 0)
offset.setWidth(-scrollPosition().x());
if (scrollPosition().y() + offset.height() < 0)
offset.setHeight(-scrollPosition().y());
setScrollPosition(scrollPosition() + offset);
notifyTransformedScrollChanged();
m_backingStore->d->orientationChanged();
m_backingStore->d->actualVisibleSizeChanged(transformedActualVisibleSize);
if (setViewMode(viewMode()))
needsLayout = true;
bool needsLayoutToFindContentSize = hasPendingOrientation;
updateViewportSize(!needsLayoutToFindContentSize , false );
notifyTransformedContentsSizeChanged();
if (!m_webSettings->isZoomToFitOnLoad()) {
atInitialScale = false;
if (!hasVirtualViewport() && contentsSize().width() < m_defaultLayoutSize.width()) {
m_mainFrame->view()->setUseFixedLayout(useFixedLayout());
m_mainFrame->view()->setFixedLayoutSize(m_defaultLayoutSize);
needsLayout = true;
}
}
m_backingStore->d->resumeBackingStoreUpdates();
bool stillNeedsLayout = needsLayout;
while (stillNeedsLayout) {
setNeedsLayout();
layoutIfNeeded();
stillNeedsLayout = false;
++m_nestedLayoutFinishedCount;
if (needsLayoutToFindContentSize) {
if (setViewMode(viewMode()))
stillNeedsLayout = true;
}
}
m_nestedLayoutFinishedCount = 0;
double scale = atInitialScale ? initialScale() : currentScale();
scale = clampedScale(scale);
if (needsLayoutToFindContentSize) {
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());
m_mainFrame->view()->repaintFixedElementsAfterScrolling();
layoutIfNeeded();
m_mainFrame->view()->updateFixedElementsAfterScrolling();
}
if (shouldSendResizeEvent())
m_mainFrame->eventHandler()->sendResizeEvent();
FloatPoint anchor = centerOfVisibleContentsRect;
if (atTop)
anchor.setY(0);
if (atLeft)
anchor.setX(0);
if (zoomAboutPoint(scale, anchor, false , true )) {
if (ensureFocusElementVisible)
ensureContentVisible(!newVisibleRectContainsOldVisibleRect);
} else {
m_backingStore->d->suspendBackingStoreUpdates();
IntPoint scrollPosition = this->scrollPosition();
if (atTop)
scrollPosition.setY(0);
if (atLeft)
scrollPosition.setX(0);
setScrollPosition(scrollPosition);
notifyTransformedContentsSizeChanged();
notifyTransformedScrollChanged();
if (!needsLayout) {
m_backingStore->d->updateTilesForScrollOrNotRenderedRegion();
}
if (ensureFocusElementVisible)
ensureContentVisible(!newVisibleRectContainsOldVisibleRect);
if (needsLayout) {
m_backingStore->d->resetTiles();
m_backingStore->d->updateTiles(false , false );
screenResumeOperation = BackingStore::RenderAndBlit;
}
m_backingStore->d->resumeBackingStoreUpdates();
}
#if ENABLE(FULLSCREEN_API) && ENABLE(VIDEO)
if (m_scaleBeforeFullScreen > 0 && !m_fullscreenNode) {
if (m_orientationBeforeFullScreen % 180 != orientation() % 180) { if (m_actualVisibleWidth > contentsSize().width() * m_scaleBeforeFullScreen) {
m_scaleBeforeFullScreen = double(m_actualVisibleWidth) / contentsSize().width();
}
if (m_scaleBeforeFullScreen * contentsSize().height() < m_actualVisibleHeight) {
m_scaleBeforeFullScreen = double(m_actualVisibleHeight) / contentsSize().height();
}
if (m_actualVisibleWidth > m_scaleBeforeFullScreen * (contentsSize().width() - m_scrollPositionBeforeFullScreen.x())) {
m_scrollPositionBeforeFullScreen.setX(contentsSize().width() - m_actualVisibleWidth / m_scaleBeforeFullScreen);
}
if (m_actualVisibleHeight > m_scaleBeforeFullScreen * (contentsSize().height() - m_scrollPositionBeforeFullScreen.y())) {
m_scrollPositionBeforeFullScreen.setY(contentsSize().height() - m_actualVisibleHeight / m_scaleBeforeFullScreen);
}
}
m_transformationMatrix->setM11(m_scaleBeforeFullScreen);
m_transformationMatrix->setM22(m_scaleBeforeFullScreen);
m_scaleBeforeFullScreen = -1.0;
setScrollPosition(m_scrollPositionBeforeFullScreen);
notifyTransformChanged();
m_client->scaleChanged();
}
#endif
m_backingStore->d->resumeScreenUpdates(screenResumeOperation);
m_inputHandler->redrawSpellCheckDialogIfRequired();
return true;
}
void WebPage::setViewportSize(const Platform::IntSize& viewportSize, const Platform::IntSize& defaultLayoutSize, bool ensureFocusElementVisible)
{
if (!d->setViewportSize(viewportSize, defaultLayoutSize, ensureFocusElementVisible)) {
setDefaultLayoutSize(defaultLayoutSize);
}
}
void WebPagePrivate::setDefaultLayoutSize(const IntSize& size)
{
IntSize screenSize = Platform::Settings::instance()->applicationSize();
ASSERT(size.width() <= screenSize.width() && size.height() <= screenSize.height());
m_defaultLayoutSize = size.expandedTo(minimumLayoutSize).shrunkTo(screenSize);
}
Platform::IntSize WebPage::defaultLayoutSize() const
{
return d->m_defaultLayoutSize;
}
void WebPage::setDefaultLayoutSize(const Platform::IntSize& platformSize)
{
bool needsLayout = false;
WebCore::IntSize size = platformSize;
if (size == d->m_defaultLayoutSize)
return;
d->setDefaultLayoutSize(size);
Platform::IntSize virtualViewportSize = d->recomputeVirtualViewportFromViewportArguments();
if (!virtualViewportSize.isEmpty()) {
setVirtualViewportSize(virtualViewportSize);
needsLayout = true;
}
if (d->setViewMode(d->viewMode()))
needsLayout = true;
if (needsLayout) {
d->setNeedsLayout();
if (!d->isLoading())
d->layoutIfNeeded();
}
}
bool WebPage::mouseEvent(const Platform::MouseEvent& mouseEvent, bool* wheelDeltaAccepted)
{
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);
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;
MouseButton buttonType = NoButton;
if (mouseEvent.isLeftButton())
buttonType = LeftButton;
else if (mouseEvent.isRightButton())
buttonType = RightButton;
else if (mouseEvent.isMiddleButton())
buttonType = MiddleButton;
PlatformMouseEvent platformMouseEvent(mouseEvent.documentViewportPosition(), mouseEvent.screenPosition(),
toWebCoreMouseEventType(mouseEvent.type()), clickCount, buttonType,
mouseEvent.shiftActive(), mouseEvent.ctrlActive(), mouseEvent.altActive(), PointingDevice);
d->m_lastMouseEvent = platformMouseEvent;
bool success = d->handleMouseEvent(platformMouseEvent);
if (mouseEvent.wheelTicks()) {
PlatformWheelEvent wheelEvent(mouseEvent.documentViewportPosition(), mouseEvent.screenPosition(),
0, -mouseEvent.wheelDelta(),
0, -mouseEvent.wheelTicks(),
ScrollByPixelWheelEvent,
mouseEvent.shiftActive(), mouseEvent.ctrlActive(),
mouseEvent.altActive(), false );
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.type() == WebCore::PlatformEvent::MouseMoved)
return eventHandler->mouseMoved(mouseEvent);
if (mouseEvent.type() == WebCore::PlatformEvent::MouseScroll)
return true;
Node* node = 0;
if (mouseEvent.inputMethod() == TouchScreen) {
const FatFingersResult lastFatFingersResult = m_touchEventHandler->lastFatFingersResult();
node = lastFatFingersResult.node(FatFingersResult::ShadowContentNotAllowed);
m_touchEventHandler->m_userTriggeredTouchPressOnTextInput = mouseEvent.type() == WebCore::PlatformEvent::MousePressed && lastFatFingersResult.isTextInput();
}
if (!node) {
IntPoint documentContentsPoint = m_webkitThreadViewportAccessor->documentContentsFromViewport(mouseEvent.position());
HitTestResult result = eventHandler->hitTestResultAtPoint(documentContentsPoint);
node = result.innerNode();
}
if (mouseEvent.type() == WebCore::PlatformEvent::MousePressed) {
m_inputHandler->setInputModeEnabled();
if (m_inputHandler->willOpenPopupForNode(node)) {
ASSERT_WITH_SECURITY_IMPLICATION(node->isElementNode());
if (node->isElementNode()) {
Element* element = toElement(node);
element->focus();
}
} else
eventHandler->handleMousePressEvent(mouseEvent);
} else if (mouseEvent.type() == WebCore::PlatformEvent::MouseReleased) {
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
Platform::logAlways(Platform::LogLevelCritical, "%s", event.toString().c_str());
#endif
#if ENABLE(TOUCH_EVENTS)
if (!d->m_mainFrame)
return false;
if (d->m_page->defersLoading())
return false;
if (d->m_inputHandler)
d->m_inputHandler->setInputModeEnabled();
PluginView* pluginView = d->m_fullScreenPluginView.get();
if (pluginView)
return d->dispatchTouchEventToFullScreenPlugin(pluginView, event);
Platform::TouchEvent tEvent = event;
if (event.isSingleTap())
d->m_pluginMayOpenNewTab = true;
else if (tEvent.m_type == Platform::TouchEvent::TouchStart || tEvent.m_type == Platform::TouchEvent::TouchCancel)
d->m_pluginMayOpenNewTab = false;
if (tEvent.m_type == Platform::TouchEvent::TouchStart) {
d->clearCachedHitTestResult();
d->m_touchEventHandler->doFatFingers(tEvent.m_points[0]);
Element* elementUnderFatFinger = d->m_touchEventHandler->lastFatFingersResult().nodeAsElementIfApplicable();
if (elementUnderFatFinger)
d->m_touchEventHandler->drawTapHighlight();
}
if (event.isTouchHold())
d->m_touchEventHandler->handleTouchHold();
bool handled = false;
if (event.m_type != Platform::TouchEvent::TouchInjected)
handled = d->m_mainFrame->eventHandler()->handleTouchEvent(PlatformTouchEvent(&tEvent));
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;
}
#endif
return false;
}
void WebPagePrivate::setScrollOriginPoint(const Platform::IntPoint& documentScrollOrigin)
{
m_inRegionScroller->d->reset();
if (!m_hasInRegionScrollableAreas)
return;
postponeDocumentStyleRecalc();
m_inRegionScroller->d->calculateInRegionScrollableAreasForPoint(documentScrollOrigin);
if (!m_inRegionScroller->d->activeInRegionScrollableAreas().empty())
m_client->notifyInRegionScrollableAreasChanged(m_inRegionScroller->d->activeInRegionScrollableAreas());
resumeDocumentStyleRecalc();
}
void WebPage::setDocumentScrollOriginPoint(const Platform::IntPoint& documentScrollOrigin)
{
d->setScrollOriginPoint(documentScrollOrigin);
}
void WebPage::touchPointAsMouseEvent(const Platform::TouchPoint& point, unsigned modifiers)
{
if (d->m_page->defersLoading())
return;
if (d->m_fullScreenPluginView.get())
return;
d->m_lastUserEventTimestamp = currentTime();
d->m_touchEventHandler->handleTouchPoint(point, modifiers);
}
void WebPage::playSoundIfAnchorIsTarget() const
{
d->m_touchEventHandler->playSoundIfAnchorIsTarget();
}
bool WebPagePrivate::dispatchTouchEventToFullScreenPlugin(PluginView* plugin, const Platform::TouchEvent& event)
{
if (!event.neverHadMultiTouch())
return false;
if (event.isDoubleTap() || event.isTouchHold() || event.m_type == Platform::TouchEvent::TouchCancel) {
NPTouchEvent npTouchEvent;
if (event.isDoubleTap())
npTouchEvent.type = TOUCH_EVENT_DOUBLETAP;
else if (event.isTouchHold())
npTouchEvent.type = TOUCH_EVENT_TOUCHHOLD;
else if (event.m_type == Platform::TouchEvent::TouchCancel)
npTouchEvent.type = TOUCH_EVENT_CANCEL;
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].id();
npTouchEvent.points[i].clientX = event.m_points[i].screenPosition().x();
npTouchEvent.points[i].clientY = event.m_points[i].screenPosition().y();
npTouchEvent.points[i].screenX = event.m_points[i].screenPosition().x();
npTouchEvent.points[i].screenY = event.m_points[i].screenPosition().y();
npTouchEvent.points[i].pageX = event.m_points[i].pixelViewportPosition().x();
npTouchEvent.points[i].pageY = event.m_points[i].pixelViewportPosition().y();
}
}
NPEvent npEvent;
npEvent.type = NP_TouchEvent;
npEvent.data = &npTouchEvent;
plugin->dispatchFullScreenNPEvent(npEvent);
delete[] npTouchEvent.points;
return true;
}
dispatchTouchPointAsMouseEventToFullScreenPlugin(plugin, event.m_points[0]);
return true;
}
bool WebPagePrivate::dispatchTouchPointAsMouseEventToFullScreenPlugin(PluginView* pluginView, const Platform::TouchPoint& point)
{
NPEvent npEvent;
NPMouseEvent mouse;
switch (point.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 true;
}
mouse.x = point.screenPosition().x();
mouse.y = point.screenPosition().y();
mouse.button = mouse.type != MOUSE_BUTTON_UP;
mouse.flags = 0;
npEvent.type = NP_MouseEvent;
npEvent.data = &mouse;
pluginView->dispatchFullScreenNPEvent(npEvent);
return true;
}
void WebPage::touchEventCancel()
{
d->m_pluginMayOpenNewTab = false;
if (d->m_page->defersLoading())
return;
}
Frame* WebPagePrivate::focusedOrMainFrame() const
{
return m_page->focusController()->focusedOrMainFrame();
}
void WebPagePrivate::clearFocusNode()
{
Frame* frame = focusedOrMainFrame();
if (!frame)
return;
ASSERT(frame->document());
if (frame->document()->focusedElement())
frame->page()->focusController()->setFocusedElement(0, frame);
}
BlackBerry::Platform::String WebPage::textEncoding()
{
Frame* frame = d->focusedOrMainFrame();
if (!frame)
return BlackBerry::Platform::String::emptyString();
Document* document = frame->document();
if (!document)
return BlackBerry::Platform::String::emptyString();
return document->loader()->writer()->encoding();
}
BlackBerry::Platform::String WebPage::forcedTextEncoding()
{
Frame* frame = d->focusedOrMainFrame();
if (!frame)
return BlackBerry::Platform::String::emptyString();
Document* document = frame->document();
if (!document)
return BlackBerry::Platform::String::emptyString();
return document->loader()->overrideEncoding();
}
void WebPage::setForcedTextEncoding(const BlackBerry::Platform::String& encoding)
{
if (!encoding.empty() && d->focusedOrMainFrame() && d->focusedOrMainFrame()->loader() && d->focusedOrMainFrame()->loader())
d->focusedOrMainFrame()->loader()->reloadWithOverrideEncoding(encoding);
}
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());
return d->m_inputHandler->handleKeyboardInput(keyboardEvent);
}
bool WebPage::deleteTextRelativeToCursor(unsigned leftOffset, unsigned rightOffset)
{
if (d->m_page->defersLoading())
return false;
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)
{
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);
}
void WebPage::setSpellCheckingEnabled(bool enabled)
{
static_cast<EditorClientBlackBerry*>(d->m_page->editorClient())->enableSpellChecking(enabled);
d->m_inputHandler->setSystemSpellCheckStatus(enabled);
if (!enabled)
d->m_inputHandler->stopPendingSpellCheckRequests();
}
void WebPage::spellCheckingRequestProcessed(int32_t transactionId, spannable_string_t* spannableString)
{
d->m_inputHandler->spellCheckingRequestProcessed(transactionId, spannableString);
}
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();
}
bool WebPage::selectionContainsDocumentPoint(const Platform::IntPoint& point)
{
return d->m_selectionHandler->selectionContains(point);
}
BlackBerry::Platform::String WebPage::title() const
{
if (d->m_mainFrame->document())
return d->m_mainFrame->loader()->documentLoader()->title().string();
return BlackBerry::Platform::String::emptyString();
}
BlackBerry::Platform::String WebPage::selectedText() const
{
return d->m_selectionHandler->selectedText();
}
BlackBerry::Platform::String WebPage::cutSelectedText()
{
BlackBerry::Platform::String selectedText = d->m_selectionHandler->selectedText();
if (!d->m_page->defersLoading() && !selectedText.empty())
d->m_inputHandler->deleteSelection();
return selectedText;
}
void WebPage::insertText(const BlackBerry::Platform::String& 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();
}
void WebPage::copy()
{
d->m_inputHandler->copy();
}
void WebPage::paste()
{
if (d->m_page->defersLoading())
return;
d->m_inputHandler->paste();
}
void WebPage::selectAll()
{
if (d->m_page->defersLoading())
return;
d->m_inputHandler->selectAll();
}
bool WebPage::isInputMode() const
{
return d->m_inputHandler->isInputMode();
}
void WebPage::setDocumentSelection(const Platform::IntPoint& documentStartPoint, const Platform::IntPoint& documentEndPoint)
{
if (d->m_page->defersLoading())
return;
d->m_selectionHandler->setSelection(documentStartPoint, documentEndPoint);
}
void WebPage::setDocumentCaretPosition(const Platform::IntPoint& documentCaretPosition)
{
if (d->m_page->defersLoading())
return;
d->m_selectionHandler->setCaretPosition(documentCaretPosition);
}
void WebPage::selectAtDocumentPoint(const Platform::IntPoint& documentPoint, SelectionExpansionType selectionExpansionType)
{
if (d->m_page->defersLoading())
return;
d->m_selectionHandler->selectAtPoint(documentPoint, selectionExpansionType);
}
void WebPage::expandSelection(bool isScrollStarted)
{
if (d->m_page->defersLoading())
return;
d->m_selectionHandler->expandSelection(isScrollStarted);
}
void WebPage::setOverlayExpansionPixelHeight(int dy)
{
d->setOverlayExpansionPixelHeight(dy);
}
void WebPagePrivate::setOverlayExpansionPixelHeight(int dy)
{
m_selectionHandler->setOverlayExpansionHeight(m_webkitThreadViewportAccessor->roundToDocumentFromPixelContents(Platform::IntPoint(0, dy)).y());
}
void WebPage::setParagraphExpansionPixelScrollMargin(const Platform::IntSize& scrollMargin)
{
Platform::IntSize documentScrollMargin = d->m_webkitThreadViewportAccessor->roundToDocumentFromPixelContents(Platform::IntRect(Platform::IntPoint(), scrollMargin)).size();
d->m_selectionHandler->setParagraphExpansionScrollMargin(documentScrollMargin);
}
void WebPage::setSelectionDocumentViewportSize(const Platform::IntSize& selectionDocumentViewportSize)
{
d->m_selectionHandler->setSelectionViewportSize(selectionDocumentViewportSize);
}
BackingStore* WebPage::backingStore() const
{
return d->m_backingStore;
}
InRegionScroller* WebPage::inRegionScroller() const
{
return d->m_inRegionScroller.get();
}
void WebPagePrivate::setTextReflowAnchorPoint(const Platform::IntPoint& documentFocalPoint)
{
ASSERT(m_webPage->settings()->textReflowMode() == WebSettings::TextReflowEnabled);
m_currentPinchZoomNode = bestNodeForZoomUnderPoint(documentFocalPoint);
if (!m_currentPinchZoomNode)
return;
IntRect nodeRect = rectForNode(m_currentPinchZoomNode.get());
m_anchorInNodeRectRatio.set(
static_cast<float>(documentFocalPoint.x() - nodeRect.x()) / nodeRect.width(),
static_cast<float>(documentFocalPoint.y() - nodeRect.y()) / nodeRect.height());
}
bool WebPage::pinchZoomAboutPoint(double scale, const Platform::FloatPoint& documentFocalPoint)
{
d->m_userPerformedManualZoom = true;
d->m_userPerformedManualScroll = true;
if (d->m_webPage->settings()->textReflowMode() == WebSettings::TextReflowEnabled) {
d->setTextReflowAnchorPoint(webkitThreadViewportAccessor()->roundedDocumentContents(documentFocalPoint));
if (!d->m_currentPinchZoomNode)
return false;
}
return d->zoomAboutPoint(scale, documentFocalPoint);
}
#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(const Platform::IntPoint& documentTargetPoint)
{
if (!d->m_mainFrame->view() || !d->isUserScalable())
return false;
Node* node = d->bestNodeForZoomUnderPoint(documentTargetPoint);
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;
const Platform::ViewportAccessor* viewportAccessor = webkitThreadViewportAccessor();
if (endOfBlockZoomMode) {
const Platform::IntSize pixelContentsSize = viewportAccessor->pixelContentsSize();
const IntRect rect = d->blockZoomRectForNode(node);
blockRect = IntRect(0, rect.y(), pixelContentsSize.width(), pixelContentsSize.height() - rect.y());
d->m_shouldReflowBlock = false;
} else {
Node* tempBlockZoomAdjustedNode = d->m_currentBlockZoomAdjustedNode.get();
blockRect = d->blockZoomRectForNode(node);
if (!node->hasTagName(HTMLNames::imgTag)) {
const IntRect tRect = viewportAccessor->roundToDocumentFromPixelContents(WebCore::FloatRect(blockRect));
int blockArea = tRect.width() * tRect.height();
int pageArea = d->contentsSize().width() * d->contentsSize().height();
double blockToPageRatio = static_cast<double>(pageArea - blockArea) / pageArea;
if (blockToPageRatio < minimumExpandingRatio) {
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 ENABLE(VIEWPORT_REFLOW)
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);
newScale = std::min(d->newScaleForBlockZoomRect(blockRect, oldScale, margin), d->maxBlockZoomScale());
newScale = std::max(newScale, minimumScale()); }
}
#endif
const Platform::FloatRect newBlockRect = viewportAccessor->documentFromPixelContents(WebCore::FloatRect(blockRect));
float scaledViewportWidth = static_cast<double>(d->actualVisibleSize().width()) * oldScale / newScale;
float scaledViewportHeight = static_cast<double>(d->actualVisibleSize().height()) * oldScale / newScale;
float dx = std::max(0.0f, (scaledViewportWidth - newBlockRect.width()) / 2.0f);
float dy = std::max(0.0f, (scaledViewportHeight - newBlockRect.height()) / 2.0f);
const RenderObject* renderer = d->m_currentBlockZoomAdjustedNode->renderer();
const FloatPoint topLeftPoint = newBlockRect.location();
FloatPoint anchor;
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 TASTART:
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());
WebCore::FloatPoint finalAnimationDocumentScrollPosition;
if (newBlockRect.height() <= scaledViewportHeight) {
finalAnimationDocumentScrollPosition = FloatPoint(anchor.x() - dx, anchor.y() - dy);
} else {
finalAnimationDocumentScrollPosition = FloatPoint(anchor.x() - dx, anchor.y() - 3);
}
#if ENABLE(VIEWPORT_REFLOW)
if (settings()->textReflowMode() != WebSettings::TextReflowDisabled) {
finalAnimationDocumentScrollPosition = FloatPoint(anchor.x() - dx, anchor.y() - 3);
d->m_finalAnimationDocumentScrollPositionReflowOffset = FloatPoint(-dx, -3);
}
#endif
FloatRect br(anchor, FloatSize(scaledViewportWidth, scaledViewportHeight));
if (!br.contains(IntPoint(documentTargetPoint))) {
d->m_finalAnimationDocumentScrollPositionReflowOffset.move(0, (documentTargetPoint.y() - scaledViewportHeight / 2) - finalAnimationDocumentScrollPosition.y());
finalAnimationDocumentScrollPosition = FloatPoint(finalAnimationDocumentScrollPosition.x(), documentTargetPoint.y() - scaledViewportHeight / 2);
}
if (finalAnimationDocumentScrollPosition.x() < 0) {
finalAnimationDocumentScrollPosition.setX(0);
d->m_finalAnimationDocumentScrollPositionReflowOffset.setX(0);
} else if (finalAnimationDocumentScrollPosition.x() + scaledViewportWidth > d->contentsSize().width()) {
finalAnimationDocumentScrollPosition.setX(d->contentsSize().width() - scaledViewportWidth);
d->m_finalAnimationDocumentScrollPositionReflowOffset.setX(0);
}
if (finalAnimationDocumentScrollPosition.y() < 0) {
finalAnimationDocumentScrollPosition.setY(0);
d->m_finalAnimationDocumentScrollPositionReflowOffset.setY(0);
} else if (finalAnimationDocumentScrollPosition.y() + scaledViewportHeight > d->contentsSize().height()) {
finalAnimationDocumentScrollPosition.setY(d->contentsSize().height() - scaledViewportHeight);
d->m_finalAnimationDocumentScrollPositionReflowOffset.setY(0);
}
if (!endOfBlockZoomMode && abs(newScale - oldScale) / oldScale < minimumExpandingRatio) {
const double minimumDisplacement = minimumExpandingRatio * viewportAccessor->documentViewportSize().width();
const int scrollPositionDisplacement = distanceBetweenPoints(viewportAccessor->documentScrollPosition(), viewportAccessor->roundedDocumentContents(finalAnimationDocumentScrollPosition));
if (oldScale == d->minimumScale() || (scrollPositionDisplacement < minimumDisplacement && abs(newScale - oldScale) / oldScale < 0.10)) {
if (isFirstZoom) {
d->resetBlockZoom();
return false;
}
blockZoom(documentTargetPoint);
return true;
}
}
d->m_userPerformedManualZoom = true;
d->m_userPerformedManualScroll = true;
d->m_client->animateToScaleAndDocumentScrollPosition(newScale, finalAnimationDocumentScrollPosition, true);
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();
}
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) {
Frame* frame = focusController->focusedFrame();
if (!frame)
focusController->setFocusedFrame(d->m_mainFrame);
}
focusController->setFocused(focused);
}
bool WebPage::findNextString(const char* text, bool forward, bool caseSensitive, bool wrap, bool highlightAllMatches, bool selectActiveMatchOnClear)
{
WebCore::FindOptions findOptions = WebCore::StartInSelection;
if (!forward)
findOptions |= WebCore::Backwards;
if (!caseSensitive)
findOptions |= WebCore::CaseInsensitive;
return d->m_inPageSearchManager->findNextString(String::fromUTF8(text), findOptions, wrap, highlightAllMatches, selectActiveMatchOnClear);
}
void WebPage::runLayoutTests()
{
#if !defined(PUBLIC_BUILD) || !PUBLIC_BUILD
d->m_page->settings()->setDeveloperExtrasEnabled(true);
if (!d->m_dumpRenderTree)
d->m_dumpRenderTree = new DumpRenderTree(this);
d->m_dumpRenderTree->runTests();
#endif
}
unsigned WebPage::timeoutForJavaScriptExecution() const
{
return Settings::timeoutForJavaScriptExecution(d->m_page->groupName());
}
void WebPage::setTimeoutForJavaScriptExecution(unsigned ms)
{
Settings::setTimeoutForJavaScriptExecution(d->m_page->groupName(), ms);
}
JSGlobalContextRef WebPage::globalContext() const
{
if (!d->m_mainFrame)
return 0;
return toGlobalRef(d->m_mainFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
}
void WebPage::getBackForwardList(SharedArray<BackForwardEntry>& result) const
{
HistoryItemVector entries = static_cast<BackForwardListBlackBerry*>(d->m_page->backForward()->client())->entries();
result.reset(new BackForwardEntry[entries.size()], entries.size());
for (unsigned i = 0; i < entries.size(); ++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());
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();
clearWebFileSystem();
}
void WebPage::clearHistory()
{
PageGroup::removeAllVisitedLinks();
}
void WebPage::clearCookies()
{
clearCookieCache();
}
void WebPage::clearLocalStorage()
{
if (PageGroup* group = d->m_page->groupPtr()) {
if (StorageNamespace* storage = group->localStorage())
storage->clearAllOriginsForDeletion();
}
}
void WebPage::clearCredentials()
{
#if ENABLE(BLACKBERRY_CREDENTIAL_PERSIST)
if (d->m_webSettings->isCredentialAutofillEnabled())
credentialManager().clearCredentials();
#endif
}
void WebPage::clearAutofillData()
{
if (d->m_webSettings->isFormAutofillEnabled())
AutofillManager::clear();
}
void WebPage::clearNeverRememberSites()
{
#if ENABLE(BLACKBERRY_CREDENTIAL_PERSIST)
if (d->m_webSettings->isCredentialAutofillEnabled())
credentialManager().clearNeverRememberSites();
#endif
}
void WebPage::clearWebFileSystem()
{
#if ENABLE(FILE_SYSTEM)
Platform::WebFileSystem::deleteAllFileSystems();
#endif
}
void WebPage::clearCache()
{
clearMemoryCaches();
clearAppCache(d->m_page->groupName());
}
void WebPage::clearBackForwardList(bool keepCurrentPage) const
{
BackForwardListBlackBerry* backForwardList = static_cast<BackForwardListBlackBerry*>(d->m_page->backForward()->client());
RefPtr<HistoryItem> currentItem = backForwardList->currentItem();
backForwardList->clear();
if (keepCurrentPage)
d->m_page->backForward()->client()->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 length)
{
ASSERT(d->m_page);
d->m_page->group().addVisitedLink(url, length);
}
void WebPage::initPopupWebView(BlackBerry::WebKit::WebPage* webPage)
{
d->m_pagePopup->initialize(webPage);
}
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();
}
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()
{
FOR_EACH_PLUGINVIEW(d->m_pluginViews)
(*it)->handleBackgroundEvent();
}
void WebPage::notifyPageForeground()
{
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 WebPagePrivate::notifyAppActivationStateChange(ActivationStateType activationState)
{
m_activationState = activationState;
#if USE(ACCELERATED_COMPOSITING)
if (activationState == ActivationActive)
resumeRootLayerCommit();
else
suspendRootLayerCommit();
#endif
#if ENABLE(PAGE_VISIBILITY_API)
setPageVisibilityState();
#endif
}
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;
}
}
d->notifyAppActivationStateChange(activationState);
}
void WebPage::notifySwipeEvent()
{
if (d->m_fullScreenPluginView.get())
d->m_fullScreenPluginView->handleSwipeEvent();
else
notifyFullScreenVideoExited(true);
}
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)
Element* element = toElement(d->m_fullscreenNode.get());
if (!element)
return;
if (d->m_webSettings->fullScreenVideoCapable() && element->hasTagName(HTMLNames::videoTag))
static_cast<HTMLMediaElement*>(element)->exitFullscreen();
#if ENABLE(FULLSCREEN_API)
else
element->document()->webkitCancelFullScreen();
#endif
#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::setExtraPluginDirectory(const BlackBerry::Platform::String& path)
{
PluginDatabase* database = PluginDatabase::installedPlugins(true );
if (!database)
return;
Vector<String> pluginDirectories = database->pluginDirectories();
if (path.empty() || pluginDirectories.contains(String(path)))
return;
pluginDirectories.append(path);
database->setPluginDirectories(pluginDirectories);
d->m_page->refreshPlugins(false );
if (d->m_webSettings->arePluginsEnabled())
database->refresh();
}
void WebPage::updateDisabledPluginFiles(const BlackBerry::Platform::String& fileName, bool disabled)
{
PluginDatabase* database = PluginDatabase::installedPlugins(true );
if (!database)
return;
if (disabled) {
if (!database->addDisabledPluginFile(fileName))
return;
} else {
if (!database->removeDisabledPluginFile(fileName))
return;
}
d->m_page->refreshPlugins(false );
if (d->m_webSettings->arePluginsEnabled())
database->refresh();
}
void WebPage::onNetworkAvailabilityChanged(bool available)
{
updateOnlineStatus(available);
}
void WebPage::onCertificateStoreLocationSet(const BlackBerry::Platform::String& caPath)
{
#if ENABLE(VIDEO)
MediaPlayerPrivate::setCertificatePath(caPath);
#endif
}
void WebPage::enableDNSPrefetch()
{
d->m_page->settings()->setDNSPrefetchingEnabled(true);
}
void WebPage::disableDNSPrefetch()
{
d->m_page->settings()->setDNSPrefetchingEnabled(false);
}
bool WebPage::isDNSPrefetchEnabled() const
{
return d->m_page->settings()->dnsPrefetchingEnabled();
}
void WebPage::enableWebInspector()
{
if (isWebInspectorEnabled() || !d->m_inspectorClient)
return;
d->m_page->inspectorController()->connectFrontend(d->m_inspectorClient);
d->m_page->settings()->setDeveloperExtrasEnabled(true);
d->setPreventsScreenDimming(true);
d->m_inspectorEnabled = true;
}
void WebPage::disableWebInspector()
{
if (!isWebInspectorEnabled())
return;
d->m_page->inspectorController()->disconnectFrontend();
d->m_page->settings()->setDeveloperExtrasEnabled(false);
d->setPreventsScreenDimming(false);
d->m_inspectorEnabled = false;
}
bool WebPage::isWebInspectorEnabled()
{
return d->m_inspectorEnabled;
}
void WebPage::enablePasswordEcho()
{
d->m_page->settings()->setPasswordEchoEnabled(true);
}
void WebPage::disablePasswordEcho()
{
d->m_page->settings()->setPasswordEchoEnabled(false);
}
void WebPage::dispatchInspectorMessage(const BlackBerry::Platform::String& message)
{
d->m_page->inspectorController()->dispatchMessageFromFrontend(message);
}
void WebPage::inspectCurrentContextElement()
{
if (isWebInspectorEnabled() && d->m_currentContextNode.get())
d->m_page->inspectorController()->inspect(d->m_currentContextNode.get());
}
Platform::IntPoint WebPage::adjustDocumentScrollPosition(const Platform::IntPoint& documentScrollPosition, const Platform::IntRect& documentPaddingRect)
{
return d->m_proximityDetector->findBestPoint(documentScrollPosition, documentPaddingRect);
}
Platform::IntSize WebPage::fixedElementSizeDelta()
{
ASSERT(Platform::userInterfaceThreadMessageClient()->isCurrentThread());
IntRect fixedElementRect;
if (d->compositor() && d->compositor()->rootLayer())
d->compositor()->findFixedElementRect(d->compositor()->rootLayer(), fixedElementRect);
if (!fixedElementRect.isEmpty() && !fixedElementRect.y())
return Platform::IntSize(0, fixedElementRect.height());
return Platform::IntSize();
}
bool WebPagePrivate::compositorDrawsRootLayer() const
{
if (!m_mainFrame)
return false;
#if USE(ACCELERATED_COMPOSITING)
if (Platform::userInterfaceThreadMessageClient()->isCurrentThread())
return m_compositor && m_compositor->drawsRootLayer();
RenderView* renderView = m_mainFrame->contentRenderer();
if (!renderView || !renderView->layer() || !renderView->layer()->backing())
return false;
return !renderView->layer()->backing()->paintsIntoWindow();
#else
return false;
#endif
}
void WebPagePrivate::setCompositorDrawsRootLayer(bool compositorDrawsRootLayer)
{
#if USE(ACCELERATED_COMPOSITING)
if (m_page->settings()->forceCompositingMode() == compositorDrawsRootLayer)
return;
m_page->settings()->setForceCompositingMode(compositorDrawsRootLayer);
m_backingStore->d->updateSuspendScreenUpdateState();
if (!m_mainFrame)
return;
if (FrameView* view = m_mainFrame->view())
view->updateCompositingLayers();
#endif
}
#if USE(ACCELERATED_COMPOSITING)
void WebPagePrivate::scheduleRootLayerCommit()
{
if (!(m_frameLayers && m_frameLayers->hasLayer()) && !m_overlayLayer)
return;
m_needsCommit = true;
if (!m_rootLayerCommitTimer->isActive()) {
#if DEBUG_AC_COMMIT
Platform::logAlways(Platform::LogLevelCritical,
"%s: m_rootLayerCommitTimer->isActive() = %d",
WTF_PRETTY_FUNCTION, m_rootLayerCommitTimer->isActive());
#endif
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(toFrameView(widget));
}
return subframesNeedsLayout;
}
LayerRenderingResults WebPagePrivate::lastCompositingResults() const
{
if (m_compositor)
return m_compositor->lastCompositingResults();
return LayerRenderingResults();
}
GraphicsLayer* WebPagePrivate::overlayLayer()
{
if (!m_overlayLayer)
m_overlayLayer = GraphicsLayer::create(0, this);
return m_overlayLayer.get();
}
void WebPagePrivate::setCompositor(PassRefPtr<WebPageCompositorPrivate> compositor)
{
using namespace BlackBerry::Platform;
ASSERT(webKitThreadMessageClient()->isCurrentThread());
m_backingStore->d->suspendScreenUpdates();
userInterfaceThreadMessageClient()->dispatchSyncMessage(createMethodCallMessage(&WebPagePrivate::setCompositorHelper, this, compositor));
m_backingStore->d->resumeScreenUpdates(BackingStore::RenderAndBlit);
}
void WebPagePrivate::setCompositorHelper(PassRefPtr<WebPageCompositorPrivate> compositor)
{
using namespace BlackBerry::Platform;
ASSERT(userInterfaceThreadMessageClient()->isCurrentThread());
m_compositor = compositor;
if (m_compositor) {
m_compositor->setPage(this);
m_compositor->setBackgroundColor(m_webSettings->backgroundColor());
}
m_ownedContext.clear();
}
void WebPagePrivate::setCompositorBackgroundColor(const Color& backgroundColor)
{
if (m_compositor)
m_compositor->setBackgroundColor(backgroundColor);
}
void WebPagePrivate::commitRootLayer(const IntRect& layoutRect, const IntRect& documentRect, bool drawsRootLayer)
{
#if DEBUG_AC_COMMIT
Platform::logAlways(Platform::LogLevelCritical,
"%s: m_compositor = 0x%p",
WTF_PRETTY_FUNCTION, m_compositor.get());
#endif
if (!m_compositor)
return;
LayerWebKitThread* rootLayer = 0;
if (m_frameLayers)
rootLayer = m_frameLayers->rootLayer();
if (rootLayer && rootLayer->layerCompositingThread() != m_compositor->rootLayer())
m_compositor->setRootLayer(rootLayer->layerCompositingThread());
LayerWebKitThread* overlayLayer = 0;
if (m_overlayLayer)
overlayLayer = m_overlayLayer->platformLayer();
if (overlayLayer && overlayLayer->layerCompositingThread() != m_compositor->overlayLayer())
m_compositor->setOverlayLayer(overlayLayer->layerCompositingThread());
m_compositor->setLayoutRect(layoutRect);
m_compositor->setDocumentRect(documentRect);
m_compositor->setDrawsRootLayer(drawsRootLayer);
if (rootLayer)
rootLayer->commitOnCompositingThread();
if (overlayLayer)
overlayLayer->commitOnCompositingThread();
m_animationStartTime = currentTime();
m_didStartAnimations = false;
if (rootLayer)
m_didStartAnimations |= rootLayer->startAnimations(m_animationStartTime);
if (overlayLayer)
m_didStartAnimations |= overlayLayer->startAnimations(m_animationStartTime);
scheduleCompositingRun();
}
bool WebPagePrivate::commitRootLayerIfNeeded()
{
#if DEBUG_AC_COMMIT
Platform::logAlways(Platform::LogLevelCritical,
"%s: m_suspendRootLayerCommit = %d, m_needsCommit = %d, m_frameLayers = 0x%p, 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;
if (!m_needsCommit)
return false;
if (!(m_frameLayers && m_frameLayers->hasLayer()) && !m_overlayLayer && !m_needsOneShotDrawingSynchronization)
return false;
FrameView* view = m_mainFrame->view();
if (!view)
return false;
updateDelegatedOverlays();
if (needsLayoutRecursive(view)) {
ASSERT(!needsOneShotDrawingSynchronization());
return false;
}
m_needsCommit = false;
m_needsOneShotDrawingSynchronization = false;
if (m_rootLayerCommitTimer->isActive())
m_rootLayerCommitTimer->stop();
double scale = currentScale();
if (m_frameLayers && m_frameLayers->hasLayer())
m_frameLayers->commitOnWebKitThread(scale);
if (m_overlayLayer)
m_overlayLayer->platformLayer()->commitOnWebKitThread(scale);
willComposite();
IntRect layoutRect(scrollPosition(), actualVisibleSize());
IntRect documentRect(view->minimumScrollPosition(), view->contentsSize());
bool drawsRootLayer = compositorDrawsRootLayer();
Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage(
Platform::createMethodCallMessage(
&WebPagePrivate::commitRootLayer,
this,
layoutRect,
documentRect,
drawsRootLayer));
if (m_didStartAnimations) {
if (m_frameLayers && m_frameLayers->hasLayer())
m_frameLayers->notifyAnimationsStarted(m_animationStartTime);
if (m_overlayLayer)
m_overlayLayer->platformLayer()->notifyAnimationsStarted(m_animationStartTime);
m_didStartAnimations = false;
}
didComposite();
return true;
}
void WebPagePrivate::rootLayerCommitTimerFired(Timer<WebPagePrivate>*)
{
if (m_suspendRootLayerCommit)
return;
#if DEBUG_AC_COMMIT
Platform::logAlways(Platform::LogLevelCritical, "%s", WTF_PRETTY_FUNCTION);
#endif
m_backingStore->d->instrumentBeginFrame();
updateLayoutAndStyleIfNeededRecursive();
if (!compositorDrawsRootLayer() && needsOneShotDrawingSynchronization()) {
#if DEBUG_AC_COMMIT
Platform::logAlways(Platform::LogLevelCritical,
"%s: OneShotDrawingSynchronization code path!",
WTF_PRETTY_FUNCTION);
#endif
const IntRect windowRect = IntRect(IntPoint::zero(), viewportSize());
m_backingStore->d->repaint(windowRect, true , true );
return;
}
commitRootLayerIfNeeded();
}
void WebPagePrivate::setRootLayerWebKitThread(Frame* frame, LayerWebKitThread* layer)
{
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;
}
if (layer && !m_compositor)
createCompositor();
if (m_compositor)
m_compositor->setRootLayer(layer);
}
bool WebPagePrivate::createCompositor()
{
if (!m_client->window())
return false;
m_ownedContext = GLES2Context::create(this);
m_compositor = WebPageCompositorPrivate::create(this, 0);
m_compositor->setContext(m_ownedContext.get());
m_compositor->setBackgroundColor(m_webSettings->backgroundColor());
return true;
}
void WebPagePrivate::destroyCompositor()
{
m_compositor->detach();
m_compositor.clear();
m_ownedContext.clear();
}
void WebPagePrivate::syncDestroyCompositorOnCompositingThread()
{
if (!m_compositor)
return;
Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage(
Platform::createMethodCallMessage(
&WebPagePrivate::destroyCompositor, this));
}
void WebPagePrivate::releaseLayerResources()
{
if (!isAcceleratedCompositingActive())
return;
if (m_frameLayers)
m_frameLayers->releaseLayerResources();
Platform::userInterfaceThreadMessageClient()->dispatchSyncMessage(
Platform::createMethodCallMessage(&WebPagePrivate::releaseLayerResourcesCompositingThread, this));
}
void WebPagePrivate::releaseLayerResourcesCompositingThread()
{
m_compositor->releaseLayerResources();
}
void WebPagePrivate::suspendRootLayerCommit()
{
if (m_suspendRootLayerCommit)
return;
m_suspendRootLayerCommit = true;
if (!m_compositor)
return;
releaseLayerResources();
}
void WebPagePrivate::resumeRootLayerCommit()
{
if (!m_suspendRootLayerCommit)
return;
m_suspendRootLayerCommit = false;
m_needsCommit = true;
scheduleRootLayerCommit();
}
bool WebPagePrivate::needsOneShotDrawingSynchronization()
{
return m_needsOneShotDrawingSynchronization;
}
void WebPagePrivate::setNeedsOneShotDrawingSynchronization()
{
if (compositorDrawsRootLayer()) {
scheduleRootLayerCommit();
return;
}
m_needsCommit = true;
m_needsOneShotDrawingSynchronization = true;
}
void WebPagePrivate::notifyFlushRequired(const GraphicsLayer*)
{
scheduleRootLayerCommit();
}
#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->getWindow();
if (!window)
return;
const char* contextName = mmrPlayer->mmrContextName();
if (!contextName)
return;
mmrPlayer->setFullscreenWebPageClient(m_client);
m_fullscreenNode = node;
m_client->fullscreenStart(contextName, window, mmrPlayer->getWindowScreenRect());
#endif
}
void WebPagePrivate::exitFullscreenForNode(Node* node)
{
#if ENABLE(VIDEO)
if (m_fullscreenNode.get()) {
m_client->fullscreenStop();
m_fullscreenNode = 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;
mmrPlayer->setFullscreenWebPageClient(0);
#endif
}
#if ENABLE(FULLSCREEN_API)
void WebPagePrivate::enterFullScreenForElement(Element* element)
{
#if ENABLE(VIDEO)
if (!element)
return;
if (m_webSettings->fullScreenVideoCapable() && element->hasTagName(HTMLNames::videoTag)) {
enterFullscreenForNode(element);
} else {
if (transformedActualVisibleSize() != transformedViewportSize()) {
m_scaleBeforeFullScreen = currentScale();
m_scrollPositionBeforeFullScreen = m_mainFrame->view()->scrollPosition();
m_orientationBeforeFullScreen = orientation();
}
client()->fullscreenStart();
m_fullscreenNode = element;
}
#endif
}
void WebPagePrivate::exitFullScreenForElement(Element* element)
{
#if ENABLE(VIDEO)
if (!element)
return;
if (m_webSettings->fullScreenVideoCapable() && element->hasTagName(HTMLNames::videoTag)) {
exitFullscreenForNode(element);
} else {
client()->fullscreenStop();
m_fullscreenNode = 0;
}
#endif
}
void WebPagePrivate::adjustFullScreenElementDimensionsIfNeeded()
{
if (!m_fullscreenNode || !m_fullscreenNode->renderer()
|| !m_fullscreenNode->document() || !m_fullscreenNode->document()->fullScreenRenderer())
return;
ASSERT(m_fullscreenNode->isElementNode());
ASSERT(toElement(m_fullscreenNode.get())->isMediaElement());
Document* document = m_fullscreenNode->document();
RenderStyle* fullScreenStyle = document->fullScreenRenderer()->style();
ASSERT(fullScreenStyle);
IntRect viewportRect = m_mainFrame->view()->visibleContentRect();
int viewportWidth = viewportRect.width() + 1;
int viewportHeight = viewportRect.height() + 1;
fullScreenStyle->setWidth(Length(viewportWidth, WebCore::Fixed));
fullScreenStyle->setHeight(Length(viewportHeight, WebCore::Fixed));
fullScreenStyle->setLeft(Length(0, WebCore::Fixed));
fullScreenStyle->setTop(Length(0, WebCore::Fixed));
fullScreenStyle->setBackgroundColor(Color::black);
document->fullScreenRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
document->recalcStyle(Node::Force);
}
#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->setDeviceSupportsMouse(webSettings->deviceSupportsMouse());
coreSettings->setDefaultFixedFontSize(webSettings->defaultFixedFontSize());
coreSettings->setDefaultFontSize(webSettings->defaultFontSize());
coreSettings->setMinimumLogicalFontSize(webSettings->minimumFontSize());
if (!webSettings->serifFontFamily().empty())
coreSettings->setSerifFontFamily(String(webSettings->serifFontFamily()));
if (!webSettings->fixedFontFamily().empty())
coreSettings->setFixedFontFamily(String(webSettings->fixedFontFamily()));
if (!webSettings->sansSerifFontFamily().empty())
coreSettings->setSansSerifFontFamily(String(webSettings->sansSerifFontFamily()));
if (!webSettings->standardFontFamily().empty())
coreSettings->setStandardFontFamily(String(webSettings->standardFontFamily()));
coreSettings->setJavaScriptCanOpenWindowsAutomatically(webSettings->canJavaScriptOpenWindowsAutomatically());
coreSettings->setAllowScriptsToCloseWindows(webSettings->canJavaScriptOpenWindowsAutomatically()); coreSettings->setPluginsEnabled(webSettings->arePluginsEnabled());
coreSettings->setDefaultTextEncodingName(webSettings->defaultTextEncodingName());
coreSettings->setDownloadableBinaryFontsEnabled(webSettings->downloadableBinaryFontsEnabled());
coreSettings->setSpatialNavigationEnabled(m_webSettings->isSpatialNavigationEnabled());
coreSettings->setAsynchronousSpellCheckingEnabled(m_webSettings->isAsynchronousSpellCheckingEnabled());
BlackBerry::Platform::String stylesheetURL = webSettings->userStyleSheetLocation();
if (!stylesheetURL.empty())
coreSettings->setUserStyleSheetLocation(KURL(KURL(), stylesheetURL));
coreSettings->setFirstScheduledLayoutDelay(webSettings->firstScheduledLayoutDelay());
coreSettings->setUseCache(webSettings->useWebKitCache());
coreSettings->setCookieEnabled(webSettings->areCookiesEnabled());
if (coreSettings->privateBrowsingEnabled() != webSettings->isPrivateBrowsingEnabled()) {
coreSettings->setPrivateBrowsingEnabled(webSettings->isPrivateBrowsingEnabled());
cookieManager().setPrivateMode(webSettings->isPrivateBrowsingEnabled());
CredentialStorage::setPrivateMode(webSettings->isPrivateBrowsingEnabled());
}
#if ENABLE(SQL_DATABASE)
static bool dbinit = false;
if (!dbinit && !webSettings->databasePath().empty()) {
dbinit = true;
DatabaseManager::manager().initialize(webSettings->databasePath());
}
static bool acinit = false;
if (!acinit && !webSettings->appCachePath().empty()) {
acinit = true;
cacheStorage().setCacheDirectory(webSettings->appCachePath());
}
coreSettings->setLocalStorageDatabasePath(webSettings->localStoragePath());
DatabaseManager::manager().setIsAvailable(webSettings->isDatabasesEnabled());
coreSettings->setLocalStorageEnabled(webSettings->isLocalStorageEnabled());
coreSettings->setOfflineWebApplicationCacheEnabled(webSettings->isAppCacheEnabled());
m_page->group().groupSettings()->setLocalStorageQuotaBytes(webSettings->localStorageQuota());
coreSettings->setSessionStorageQuota(webSettings->sessionStorageQuota());
coreSettings->setUsesPageCache(webSettings->maximumPagesInCache());
coreSettings->setFrameFlatteningEnabled(webSettings->isFrameFlatteningEnabled());
#endif
#if ENABLE(INDEXED_DATABASE)
m_page->group().groupSettings()->setIndexedDBDatabasePath(webSettings->indexedDataBasePath());
#endif
#if ENABLE(WEB_SOCKETS)
WebSocket::setIsAvailable(webSettings->areWebSocketsEnabled());
#endif
#if ENABLE(FULLSCREEN_API)
coreSettings->setFullScreenEnabled(true);
#endif
#if ENABLE(VIEWPORT_REFLOW)
coreSettings->setTextReflowEnabled(webSettings->textReflowMode() == WebSettings::TextReflowEnabled);
#endif
coreSettings->setShouldUseFirstScheduledLayoutDelay(webSettings->isEmailMode());
coreSettings->setProcessHTTPEquiv(!webSettings->isEmailMode());
coreSettings->setShouldUseCrossOriginProtocolCheck(!webSettings->allowCrossSiteRequests());
coreSettings->setWebSecurityEnabled(!webSettings->allowCrossSiteRequests());
coreSettings->setApplyDeviceScaleFactorInCompositor(webSettings->applyDeviceScaleFactorInCompositor());
updateBackgroundColor(webSettings->backgroundColor());
m_page->setDeviceScaleFactor(webSettings->devicePixelRatio());
#if ENABLE(TEXT_AUTOSIZING)
coreSettings->setTextAutosizingEnabled(webSettings->isTextAutosizingEnabled());
#endif
}
BlackBerry::Platform::String WebPage::textHasAttribute(const BlackBerry::Platform::String& query) const
{
if (Document* doc = d->m_page->focusController()->focusedOrMainFrame()->document())
return doc->queryCommandValue(query);
return BlackBerry::Platform::String::emptyString();
}
void WebPage::setJavaScriptCanAccessClipboard(bool enabled)
{
d->m_page->settings()->setJavaScriptCanAccessClipboard(enabled);
}
#if USE(ACCELERATED_COMPOSITING)
void WebPagePrivate::scheduleCompositingRun()
{
if (WebPageCompositorClient* compositorClient = compositor()->client()) {
double animationTime = compositorClient->requestAnimationFrame();
compositorClient->invalidate(animationTime);
return;
}
m_backingStore->d->blitVisibleContents();
}
#endif
void WebPage::setWebGLEnabled(bool enabled)
{
d->m_page->settings()->setWebGLEnabled(enabled);
}
bool WebPage::isWebGLEnabled() const
{
return d->m_page->settings()->webGLEnabled();
}
void WebPagePrivate::frameUnloaded(const Frame* frame)
{
m_inputHandler->frameUnloaded(frame);
m_inPageSearchManager->frameUnloaded(frame);
}
const BlackBerry::Platform::String& WebPagePrivate::defaultUserAgent()
{
static BlackBerry::Platform::String* defaultUserAgent = 0;
if (!defaultUserAgent) {
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 = new BlackBerry::Platform::String(BlackBerry::Platform::String::fromUtf8(uaBuffer, uaSize));
}
return *defaultUserAgent;
}
WebTapHighlight* WebPage::tapHighlight() const
{
return d->m_tapHighlight.get();
}
WebTapHighlight* WebPage::selectionHighlight() const
{
return d->m_selectionHighlight.get();
}
void WebPage::addOverlay(WebOverlay* overlay)
{
#if USE(ACCELERATED_COMPOSITING)
if (overlay->d->graphicsLayer()) {
overlay->d->setPage(d);
d->overlayLayer()->addChild(overlay->d->graphicsLayer());
}
#endif
}
void WebPage::removeOverlay(WebOverlay* overlay)
{
#if USE(ACCELERATED_COMPOSITING)
if (overlay->d->graphicsLayer()->parent() != d->overlayLayer())
return;
overlay->removeFromParent();
overlay->d->clear();
overlay->d->setPage(0);
#endif
}
void WebPage::addCompositingThreadOverlay(WebOverlay* overlay)
{
#if USE(ACCELERATED_COMPOSITING)
ASSERT(Platform::userInterfaceThreadMessageClient()->isCurrentThread());
if (!d->compositor())
return;
overlay->d->setPage(d);
d->compositor()->addOverlay(overlay->d->layerCompositingThread());
#endif
}
void WebPage::removeCompositingThreadOverlay(WebOverlay* overlay)
{
#if USE(ACCELERATED_COMPOSITING)
ASSERT(Platform::userInterfaceThreadMessageClient()->isCurrentThread());
if (d->compositor())
d->compositor()->removeOverlay(overlay->d->layerCompositingThread());
overlay->d->clear();
overlay->d->setPage(0);
#endif
}
bool WebPagePrivate::openPagePopup(PagePopupClient* popupClient, const WebCore::IntRect& originBoundsInRootView)
{
closePagePopup();
m_pagePopup = PagePopup::create(this, popupClient);
WebCore::IntRect popupRect = m_page->chrome().client()->rootViewToScreen(originBoundsInRootView);
popupRect.setSize(popupClient->contentSize());
if (!m_client->createPopupWebView(popupRect)) {
closePagePopup();
return false;
}
return true;
}
void WebPagePrivate::closePagePopup()
{
if (!m_pagePopup)
return;
m_pagePopup->close();
m_client->closePopupWebView();
m_pagePopup = 0;
}
bool WebPagePrivate::hasOpenedPopup() const
{
return m_pagePopup;
}
void WebPagePrivate::setInspectorOverlayClient(InspectorOverlay::InspectorOverlayClient* inspectorOverlayClient)
{
if (inspectorOverlayClient) {
if (!m_inspectorOverlay)
m_inspectorOverlay = InspectorOverlay::create(this, inspectorOverlayClient);
else
m_inspectorOverlay->setClient(inspectorOverlayClient);
m_inspectorOverlay->update();
scheduleRootLayerCommit();
} else {
if (m_inspectorOverlay) {
m_inspectorOverlay->clear();
m_inspectorOverlay = nullptr;
scheduleRootLayerCommit();
}
}
}
void WebPagePrivate::applySizeOverride(int overrideWidth, int overrideHeight)
{
m_client->requestUpdateViewport(overrideWidth, overrideHeight);
}
void WebPagePrivate::setTextZoomFactor(float textZoomFactor)
{
if (!m_mainFrame)
return;
m_mainFrame->setTextZoomFactor(textZoomFactor);
}
void WebPagePrivate::restoreHistoryViewState(const WebCore::IntPoint& scrollPosition, double scale, bool shouldReflowBlock)
{
if (!m_mainFrame) {
m_backingStore->d->resumeBackingStoreUpdates();
m_backingStore->d->resumeScreenUpdates(BackingStore::RenderAndBlit);
return;
}
WebCore::IntPoint adjustedScrollPosition = scrollPosition;
WebCore::IntSize validContentsSize = contentsSize();
WebCore::IntSize viewportSize = actualVisibleSize();
if (adjustedScrollPosition.x() + viewportSize.width() > validContentsSize.width())
adjustedScrollPosition.setX(validContentsSize.width() - viewportSize.width());
if (adjustedScrollPosition.y() + viewportSize.height() > validContentsSize.height())
adjustedScrollPosition.setY(validContentsSize.height() - viewportSize.height());
bool oldConstrainsScrollingToContentEdge = m_mainFrame->view()->constrainsScrollingToContentEdge();
m_mainFrame->view()->setConstrainsScrollingToContentEdge(false);
setScrollPosition(adjustedScrollPosition);
m_mainFrame->view()->setConstrainsScrollingToContentEdge(oldConstrainsScrollingToContentEdge);
m_shouldReflowBlock = shouldReflowBlock;
if (!zoomAboutPoint(scale, m_mainFrame->view()->scrollPosition(), true , true , true )) {
notifyTransformedContentsSizeChanged();
notifyTransformedScrollChanged();
}
m_backingStore->d->resumeBackingStoreUpdates();
m_backingStore->d->resumeScreenUpdates(BackingStore::RenderAndBlit);
}
IntSize WebPagePrivate::screenSize() const
{
return Platform::Graphics::Screen::primaryScreen()->size();
}
void WebPagePrivate::postponeDocumentStyleRecalc()
{
if (Document* document = m_mainFrame->document()) {
m_documentChildNeedsStyleRecalc = document->childNeedsStyleRecalc();
document->clearChildNeedsStyleRecalc();
m_documentStyleRecalcPostponed = document->hasPendingStyleRecalc();
document->unscheduleStyleRecalc();
}
}
void WebPagePrivate::resumeDocumentStyleRecalc()
{
if (Document* document = m_mainFrame->document()) {
if (m_documentChildNeedsStyleRecalc)
document->setChildNeedsStyleRecalc();
if (m_documentStyleRecalcPostponed)
document->scheduleStyleRecalc();
}
m_documentChildNeedsStyleRecalc = false;
m_documentStyleRecalcPostponed = false;
}
const HitTestResult& WebPagePrivate::hitTestResult(const IntPoint& contentPos)
{
if (m_cachedHitTestContentPos != contentPos) {
m_cachedHitTestContentPos = contentPos;
m_cachedRectHitTestResults.clear();
m_cachedHitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(m_cachedHitTestContentPos, HitTestRequest::ReadOnly | HitTestRequest::Active);
}
return m_cachedHitTestResult;
}
void WebPagePrivate::clearCachedHitTestResult()
{
m_cachedHitTestContentPos = WebCore::IntPoint(-1, -1);
}
void WebPagePrivate::willComposite()
{
if (!m_page->settings()->developerExtrasEnabled())
return;
m_page->inspectorController()->willComposite();
}
void WebPagePrivate::didComposite()
{
if (!m_page->settings()->developerExtrasEnabled())
return;
m_page->inspectorController()->didComposite();
}
void WebPage::updateNotificationPermission(const BlackBerry::Platform::String& requestId, bool allowed)
{
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
d->notificationManager().updatePermission(requestId, allowed);
#else
UNUSED_PARAM(requestId);
UNUSED_PARAM(allowed);
#endif
}
void WebPage::notificationClicked(const BlackBerry::Platform::String& notificationId)
{
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
d->notificationManager().notificationClicked(notificationId);
#else
UNUSED_PARAM(notificationId);
#endif
}
void WebPage::notificationClosed(const BlackBerry::Platform::String& notificationId)
{
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
d->notificationManager().notificationClosed(notificationId);
#else
UNUSED_PARAM(notificationId);
#endif
}
void WebPage::notificationError(const BlackBerry::Platform::String& notificationId)
{
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
d->notificationManager().notificationError(notificationId);
#else
UNUSED_PARAM(notificationId);
#endif
}
void WebPage::notificationShown(const BlackBerry::Platform::String& notificationId)
{
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
d->notificationManager().notificationShown(notificationId);
#else
UNUSED_PARAM(notificationId);
#endif
}
void WebPagePrivate::animateToScaleAndDocumentScrollPosition(double destinationZoomScale, const WebCore::FloatPoint& destinationScrollPosition, bool shouldConstrainScrollingToContentEdge)
{
if (destinationScrollPosition == scrollPosition() && destinationZoomScale == currentScale())
return;
m_shouldReflowBlock = false;
m_userPerformedManualZoom = true;
m_userPerformedManualScroll = true;
client()->animateToScaleAndDocumentScrollPosition(destinationZoomScale, destinationScrollPosition, shouldConstrainScrollingToContentEdge);
}
void WebPage::animateToScaleAndDocumentScrollPosition(double destinationZoomScale, const BlackBerry::Platform::FloatPoint& destinationScrollPosition, bool shouldConstrainScrollingToContentEdge)
{
d->animateToScaleAndDocumentScrollPosition(destinationZoomScale, destinationScrollPosition, shouldConstrainScrollingToContentEdge);
}
void WebPagePrivate::updateBackgroundColor(const Color& backgroundColor)
{
if (!m_mainFrame || !m_mainFrame->view())
return;
m_mainFrame->view()->updateBackgroundRecursively(backgroundColor, backgroundColor.hasAlpha());
Platform::userInterfaceThreadMessageClient()->dispatchMessage(
createMethodCallMessage(&WebPagePrivate::setCompositorBackgroundColor, this, backgroundColor));
if (m_backingStore)
m_backingStore->d->setWebPageBackgroundColor(documentBackgroundColor());
}
Color WebPagePrivate::documentBackgroundColor() const
{
Color color;
if (m_mainFrame && m_mainFrame->view())
color = m_mainFrame->view()->documentBackgroundColor();
if (!color.isValid())
color = m_webSettings->backgroundColor();
return color;
}
bool WebPage::isProcessingUserGesture() const
{
return ScriptController::processingUserGesture();
}
#if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER)
void WebPagePrivate::animationFrameChanged()
{
if (!m_animationMutex.tryLock())
return;
if (!m_previousFrameDone) {
m_animationMutex.unlock();
return;
}
if (!m_animationScheduled) {
stopRefreshAnimationClient();
m_animationMutex.unlock();
return;
}
m_previousFrameDone = false;
m_monotonicAnimationStartTime = monotonicallyIncreasingTime();
callOnMainThread(handleServiceScriptedAnimationsOnMainThread, this);
m_animationMutex.unlock();
}
void WebPagePrivate::scheduleAnimation()
{
if (m_animationScheduled)
return;
MutexLocker lock(m_animationMutex);
m_animationScheduled = true;
startRefreshAnimationClient();
}
void WebPagePrivate::startRefreshAnimationClient()
{
if (m_isRunningRefreshAnimationClient)
return;
m_isRunningRefreshAnimationClient = true;
BlackBerry::Platform::AnimationFrameRateController::instance()->addClient(this);
}
void WebPagePrivate::stopRefreshAnimationClient()
{
if (!m_isRunningRefreshAnimationClient)
return;
m_isRunningRefreshAnimationClient = false;
BlackBerry::Platform::AnimationFrameRateController::instance()->removeClient(this);
}
void WebPagePrivate::serviceAnimations()
{
double monotonicAnimationStartTime;
{
MutexLocker lock(m_animationMutex);
m_animationScheduled = false;
monotonicAnimationStartTime = m_monotonicAnimationStartTime;
}
m_mainFrame->view()->serviceScriptedAnimations(monotonicAnimationStartTime);
{
MutexLocker lock(m_animationMutex);
m_previousFrameDone = true;
}
}
void WebPagePrivate::handleServiceScriptedAnimationsOnMainThread(void* data)
{
static_cast<WebPagePrivate*>(data)->serviceAnimations();
}
#endif
void WebPage::setShowDebugBorders(bool show)
{
#if USE(ACCELERATED_COMPOSITING)
d->m_page->settings()->setShowDebugBorders(show);
#endif
}
}
}