diff options
75 files changed, 1571 insertions, 1045 deletions
@@ -333,6 +333,11 @@ WEBKIT_LDLIBS := $(LOCAL_LDLIBS) WEBKIT_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES) WEBKIT_STATIC_LIBRARIES := $(LOCAL_STATIC_LIBRARIES) +ifneq ($(strip $(WITH_ADDRESS_SANITIZER)),) + LOCAL_MODULE_PATH := $(TARGET_OUT_STATIC_LIBRARIES)/asan + LOCAL_ADDRESS_SANITIZER := true +endif + # Build the library all at once include $(BUILD_STATIC_LIBRARY) @@ -374,6 +379,12 @@ endif # We make all of our object files depend on those files so that they are built # before we try to compile the file. LOCAL_ADDITIONAL_DEPENDENCIES := $(filter %.h, $(WEBKIT_GENERATED_SOURCES)) + +ifneq ($(strip $(WITH_ADDRESS_SANITIZER)),) + LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/asan + LOCAL_ADDRESS_SANITIZER := true +endif + include $(BUILD_SHARED_LIBRARY) # Build the wds client diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h index a1db9d6..41850ee 100644 --- a/Source/JavaScriptCore/wtf/Platform.h +++ b/Source/JavaScriptCore/wtf/Platform.h @@ -726,6 +726,7 @@ #define ENABLE_OFFLINE_WEB_APPLICATIONS 1 #define ENABLE_TOUCH_EVENTS 1 #define ENABLE_GEOLOCATION 1 +#define ENABLE_CLIENT_BASED_GEOLOCATION 1 #define ENABLE_INSPECTOR 0 #define ENABLE_EVENT_SOURCE 0 #define ENABLE_DEVICE_ORIENTATION 1 @@ -779,8 +780,6 @@ #define ANDROID_ANIMATED_GIF // apple-touch-icon support in <link> tags #define ANDROID_APPLE_TOUCH_ICON -// track changes to the style that may change what is drawn -#define ANDROID_STYLE_VERSION // This is present in JavaScriptCore/config.h, which Android does not use. #define WTF_CHANGES 1 diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk index 742fade..f4f9bca 100644 --- a/Source/WebCore/Android.mk +++ b/Source/WebCore/Android.mk @@ -496,6 +496,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ page/FrameTree.cpp \ page/FrameView.cpp \ page/Geolocation.cpp \ + page/GeolocationController.cpp \ page/GeolocationPositionCache.cpp \ page/GroupSettings.cpp \ page/History.cpp \ @@ -545,7 +546,6 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/FileChooser.cpp \ platform/FileStream.cpp \ platform/FileSystem.cpp \ - platform/GeolocationService.cpp \ platform/KURL.cpp \ platform/KURLGoogle.cpp \ platform/KillRingNone.cpp \ @@ -576,8 +576,6 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/android/EventLoopAndroid.cpp \ platform/android/FileChooserAndroid.cpp \ platform/android/FileSystemAndroid.cpp \ - platform/android/GeolocationServiceAndroid.cpp \ - platform/android/GeolocationServiceBridge.cpp \ platform/android/KeyEventAndroid.cpp \ platform/android/LanguageAndroid.cpp \ platform/android/LocalizedStringsAndroid.cpp \ @@ -757,7 +755,6 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ \ platform/mock/DeviceOrientationClientMock.cpp \ platform/mock/GeolocationClientMock.cpp \ - platform/mock/GeolocationServiceMock.cpp \ platform/mock/SpeechInputClientMock.cpp \ \ platform/network/AuthenticationChallengeBase.cpp \ diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp index b6a1393..96be3fb 100644 --- a/Source/WebCore/dom/Document.cpp +++ b/Source/WebCore/dom/Document.cpp @@ -387,9 +387,6 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML) , m_compatibilityMode(NoQuirksMode) , m_compatibilityModeLocked(false) , m_domTreeVersion(++s_globalTreeVersion) -#ifdef ANDROID_STYLE_VERSION - , m_styleVersion(0) -#endif , m_styleSheets(StyleSheetList::create(this)) , m_readyState(Complete) , m_styleRecalcTimer(this, &Document::styleRecalcTimerFired) diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h index ce82b2e..c4ccb9c 100644 --- a/Source/WebCore/dom/Document.h +++ b/Source/WebCore/dom/Document.h @@ -905,11 +905,6 @@ public: void incDOMTreeVersion() { m_domTreeVersion = ++s_globalTreeVersion; } uint64_t domTreeVersion() const { return m_domTreeVersion; } -#ifdef ANDROID_STYLE_VERSION - void incStyleVersion() { ++m_styleVersion; } - unsigned styleVersion() const { return m_styleVersion; } -#endif - void setDocType(PassRefPtr<DocumentType>); #if ENABLE(XPATH) @@ -1223,9 +1218,6 @@ private: uint64_t m_domTreeVersion; static uint64_t s_globalTreeVersion; -#ifdef ANDROID_STYLE_VERSION - unsigned m_styleVersion; -#endif HashSet<NodeIterator*> m_nodeIterators; HashSet<Range*> m_ranges; diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp index 64d3eed..5fb6cdc 100644 --- a/Source/WebCore/dom/Element.cpp +++ b/Source/WebCore/dom/Element.cpp @@ -1069,21 +1069,6 @@ bool Element::pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderS return false; } -#ifdef ANDROID_STYLE_VERSION -static bool displayDiff(const RenderStyle* s1, const RenderStyle* s2) -{ - if (!s1 && !s2) - return false; - else if ((!s1 && s2) || (s1 && !s2)) - return true; - - return s1->display() != s2->display() - || s1->left() != s2->left() || s1->top() != s2->top() - || s1->right() != s2->right() || s1->bottom() != s2->bottom() - || s1->width() != s2->width() || s1->height() != s2->height(); -} -#endif - void Element::recalcStyle(StyleChange change) { // Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called. @@ -1092,11 +1077,6 @@ void Element::recalcStyle(StyleChange change) bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules(); if ((change > NoChange || needsStyleRecalc())) { -#ifdef ANDROID_STYLE_VERSION - RefPtr<RenderStyle> newStyle = document()->styleForElementIgnoringPendingStylesheets(this); - if (displayDiff(currentStyle.get(), newStyle.get())) - document()->incStyleVersion(); -#endif if (hasRareData()) rareData()->resetComputedStyle(); } diff --git a/Source/WebCore/page/Geolocation.cpp b/Source/WebCore/page/Geolocation.cpp index f0dd76a..352e06b 100644 --- a/Source/WebCore/page/Geolocation.cpp +++ b/Source/WebCore/page/Geolocation.cpp @@ -708,20 +708,8 @@ bool Geolocation::startUpdating(GeoNotifier* notifier) page->geolocationController()->addObserver(this, notifier->m_options->enableHighAccuracy()); return true; #else -#if PLATFORM(ANDROID) - // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082 - // Note that the correct fix is to use a 'paused' flag in WebCore, rather - // than calling into PlatformBridge. - if (!m_frame) - return false; - FrameView* view = m_frame->view(); - if (!view) - return false; - return m_service->startUpdating(notifier->m_options.get(), PlatformBridge::isWebViewPaused(view)); -#else return m_service->startUpdating(notifier->m_options.get()); #endif -#endif } void Geolocation::stopUpdating() diff --git a/Source/WebCore/page/GeolocationController.cpp b/Source/WebCore/page/GeolocationController.cpp index b9533ca..56c11a5 100644 --- a/Source/WebCore/page/GeolocationController.cpp +++ b/Source/WebCore/page/GeolocationController.cpp @@ -59,7 +59,10 @@ void GeolocationController::addObserver(Geolocation* observer, bool enableHighAc if (m_client) { if (enableHighAccuracy) m_client->setEnableHighAccuracy(true); +// See https://bugs.webkit.org/show_bug.cgi?id=87030 +#if !PLATFORM(ANDROID) if (wasEmpty) +#endif m_client->startUpdating(); } } diff --git a/Source/WebCore/platform/GeolocationService.h b/Source/WebCore/platform/GeolocationService.h index 27be6c3..1045bb3 100644 --- a/Source/WebCore/platform/GeolocationService.h +++ b/Source/WebCore/platform/GeolocationService.h @@ -48,12 +48,7 @@ public: static GeolocationService* create(GeolocationServiceClient*); virtual ~GeolocationService() { } -#if PLATFORM(ANDROID) - // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082 - virtual bool startUpdating(PositionOptions*, bool suspend) { return false; } -#else virtual bool startUpdating(PositionOptions*) { return false; } -#endif virtual void stopUpdating() { } virtual void suspend() { } diff --git a/Source/WebCore/platform/android/GeolocationServiceAndroid.cpp b/Source/WebCore/platform/android/GeolocationServiceAndroid.cpp deleted file mode 100644 index 0f07722..0000000 --- a/Source/WebCore/platform/android/GeolocationServiceAndroid.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "GeolocationServiceAndroid.h" - -#include "Geolocation.h" -#include "GeolocationServiceBridge.h" -#include "Geoposition.h" -#include "PositionError.h" -#include "PositionOptions.h" - -#if PLATFORM(ANDROID) -// Required for sim-eng build -#include <math.h> -#endif -#include <wtf/CurrentTime.h> - -using JSC::Bindings::getJNIEnv; -using namespace std; - -namespace WebCore { - -// GeolocationServiceAndroid is the Android implmentation of Geolocation -// service. Each object of this class owns an object of type -// GeolocationServiceBridge, which in turn owns a Java GeolocationService -// object. Therefore, there is a 1:1 mapping between Geolocation, -// GeolocationServiceAndroid, GeolocationServiceBridge and Java -// GeolocationService objects. In the case where multiple Geolocation objects -// exist simultaneously, the corresponsing Java GeolocationService objects all -// register with the platform location service. It is the platform service that -// handles making sure that updates are passed to all Geolocation objects. -GeolocationService* GeolocationServiceAndroid::create(GeolocationServiceClient* client) -{ - return new GeolocationServiceAndroid(client); -} - -GeolocationService::FactoryFunction* GeolocationService::s_factoryFunction = &GeolocationServiceAndroid::create; - -GeolocationServiceAndroid::GeolocationServiceAndroid(GeolocationServiceClient* client) - : GeolocationService(client) - , m_timer(this, &GeolocationServiceAndroid::timerFired) - , m_javaBridge(0) -{ -} - -// ANDROID -// TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082 -bool GeolocationServiceAndroid::startUpdating(PositionOptions* options, bool suspend) -{ - // ANDROID - // This is an ugly hack. A correct fix would require a change to WebCore, - // but this isn't worth the effort as we're in the process of switching to a - // client-based implementation. See https://bugs.webkit.org/show_bug.cgi?id=40373 - Frame* frame = reinterpret_cast<Geolocation*>(geolocationServiceClient())->frame(); - if (!frame) - return false; - - // This method is called every time a new watch or one-shot position request - // is started. If we already have a position or an error, call back - // immediately. - if (m_lastPosition || m_lastError) { - ASSERT(m_javaBridge); - m_timer.startOneShot(0); - } - - // Lazilly create the Java object. - bool haveJavaBridge = m_javaBridge; - if (!haveJavaBridge) - m_javaBridge.set(new GeolocationServiceBridge(this, frame)); - ASSERT(m_javaBridge); - - // On Android, high power == GPS. Set whether to use GPS before we start the - // implementation. - ASSERT(options); - if (options->enableHighAccuracy()) - m_javaBridge->setEnableGps(true); - - // We need only start the service when it's first created. - if (!haveJavaBridge) { - // If the browser is paused, don't start the service. It will be started - // when we get the call to resume. - // ANDROID - // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082 - if (!suspend) - return m_javaBridge->start(); - } - - return true; -} - -void GeolocationServiceAndroid::stopUpdating() -{ - // Called when the Geolocation object has no watches or one shots in - // progress. This may be called repeatedly. - m_javaBridge.clear(); - // Reset last position and error to make sure that we always try to get a - // new position from the system service when a request is first made. - m_lastPosition = 0; - m_lastError = 0; - // remove the pending timer - if (m_timer.isActive()) - m_timer.stop(); -} - -void GeolocationServiceAndroid::suspend() -{ - if (m_javaBridge) - m_javaBridge->stop(); -} - -void GeolocationServiceAndroid::resume() -{ - if (m_javaBridge) - m_javaBridge->start(); -} - -// Note that there is no guarantee that subsequent calls to this method offer a -// more accurate or updated position. -void GeolocationServiceAndroid::newPositionAvailable(PassRefPtr<Geoposition> position) -{ - ASSERT(position); - if (!m_lastPosition - || isPositionMovement(m_lastPosition.get(), position.get()) - || isPositionMoreAccurate(m_lastPosition.get(), position.get()) - || isPositionMoreTimely(m_lastPosition.get(), position.get())) { - m_lastPosition = position; - // Remove the last error. - m_lastError = 0; - positionChanged(); - } -} - -void GeolocationServiceAndroid::newErrorAvailable(PassRefPtr<PositionError> error) -{ - ASSERT(error); - // We leave the last position - m_lastError = error; - errorOccurred(); -} - -void GeolocationServiceAndroid::timerFired(Timer<GeolocationServiceAndroid>* timer) -{ - ASSERT(&m_timer == timer); - ASSERT(m_lastPosition || m_lastError); - if (m_lastPosition) - positionChanged(); - else if (m_lastError) - errorOccurred(); -} - -bool GeolocationServiceAndroid::isPositionMovement(Geoposition* position1, Geoposition* position2) -{ - ASSERT(position1 && position2); - // For the small distances in which we are likely concerned, it's reasonable - // to approximate the distance between the two positions as the sum of the - // differences in latitude and longitude. - double delta = fabs(position1->coords()->latitude() - position2->coords()->latitude()) - + fabs(position1->coords()->longitude() - position2->coords()->longitude()); - // Approximate conversion from degrees of arc to metres. - delta *= 60 * 1852; - // The threshold is when the distance between the two positions exceeds the - // worse (larger) of the two accuracies. - int maxAccuracy = max(position1->coords()->accuracy(), position2->coords()->accuracy()); - return delta > maxAccuracy; -} - -bool GeolocationServiceAndroid::isPositionMoreAccurate(Geoposition* position1, Geoposition* position2) -{ - ASSERT(position1 && position2); - return position2->coords()->accuracy() < position1->coords()->accuracy(); -} - -bool GeolocationServiceAndroid::isPositionMoreTimely(Geoposition* position1, Geoposition* position2) -{ - ASSERT(position1 && position2); - DOMTimeStamp currentTime = convertSecondsToDOMTimeStamp(WTF::currentTime()); - DOMTimeStamp maximumAge = convertSecondsToDOMTimeStamp(10 * 60); // 10 minutes - return currentTime - position1->timestamp() > maximumAge; -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/android/GeolocationServiceAndroid.h b/Source/WebCore/platform/android/GeolocationServiceAndroid.h deleted file mode 100644 index 72532f6..0000000 --- a/Source/WebCore/platform/android/GeolocationServiceAndroid.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GeolocationServiceAndroid_h -#define GeolocationServiceAndroid_h - -#include "GeolocationService.h" -#include "Timer.h" -#include <wtf/OwnPtr.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - -// The GeolocationServiceBridge is the bridge to the Java implementation of -// the Geolocation service. It is an implementation detail of -// GeolocationServiceAndroid. -class GeolocationServiceBridge; - -class GeolocationServiceAndroid : public GeolocationService { -public: - static GeolocationService* create(GeolocationServiceClient*); - - virtual ~GeolocationServiceAndroid() { }; - - // ANDROID - // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082 - virtual bool startUpdating(PositionOptions*, bool suspend); - virtual void stopUpdating(); - - virtual Geoposition* lastPosition() const { return m_lastPosition.get(); } - virtual PositionError* lastError() const { return m_lastError.get(); } - - virtual void suspend(); - virtual void resume(); - - // Android-specific - void newPositionAvailable(PassRefPtr<Geoposition>); - void newErrorAvailable(PassRefPtr<PositionError>); - void timerFired(Timer<GeolocationServiceAndroid>* timer); - -private: - GeolocationServiceAndroid(GeolocationServiceClient*); - - static bool isPositionMovement(Geoposition* position1, Geoposition* position2); - static bool isPositionMoreAccurate(Geoposition* position1, Geoposition* position2); - static bool isPositionMoreTimely(Geoposition* position1, Geoposition* position2); - - Timer<GeolocationServiceAndroid> m_timer; - RefPtr<Geoposition> m_lastPosition; - RefPtr<PositionError> m_lastError; - OwnPtr<GeolocationServiceBridge> m_javaBridge; -}; - -} // namespace WebCore - -#endif // GeolocationServiceAndroid_h diff --git a/Source/WebCore/platform/android/PlatformBridge.h b/Source/WebCore/platform/android/PlatformBridge.h index a4c1048..e48e50c 100644 --- a/Source/WebCore/platform/android/PlatformBridge.h +++ b/Source/WebCore/platform/android/PlatformBridge.h @@ -124,10 +124,6 @@ public: }; static String* globalLocalizedName(rawResId resId); - // Whether the WebView is paused. - // ANDROID - // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082 - static bool isWebViewPaused(const FrameView*); static String resolveFilePathForContentUri(const String&); static int screenDepth(); diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index 55c4eec..20f5abf 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -355,7 +355,7 @@ int GLWebViewState::drawGL(IntRect& invScreenRect, SkRect& visibleContentRect, if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) { ALOGW("WARNING, scale seems corrupted after update: %e", scale); - scale = 1.0f; // WORKAROUND for corrupted scale: use 1.0 + CRASH(); } double currentTime = setupDrawing(invScreenRect, visibleContentRect, screenRect, diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 779dba5..5fe9a1f 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -853,6 +853,7 @@ bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer, if (!layer) return false; + TRACE_METHOD(); SkPicture* picture = paintPicture(rect); if (!picture) return false; diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp index 9e6208d..829be2e 100644 --- a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp @@ -13,8 +13,7 @@ namespace WebCore { -GraphicsOperationCollection::GraphicsOperationCollection(const IntRect& drawArea) - : m_drawArea(drawArea) +GraphicsOperationCollection::GraphicsOperationCollection() { } @@ -44,9 +43,9 @@ bool GraphicsOperationCollection::isEmpty() return !m_operations.size(); } -AutoGraphicsOperationCollection::AutoGraphicsOperationCollection(const IntRect& area) +AutoGraphicsOperationCollection::AutoGraphicsOperationCollection() { - m_graphicsOperationCollection = new GraphicsOperationCollection(area); + m_graphicsOperationCollection = new GraphicsOperationCollection(); m_platformGraphicsContext = new PlatformGraphicsContextRecording(m_graphicsOperationCollection); m_graphicsContext = new GraphicsContext(m_platformGraphicsContext); } diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h index 9d7b530..d3fc16b 100644 --- a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h +++ b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h @@ -39,7 +39,7 @@ class PlatformGraphicsContext; class GraphicsOperationCollection : public SkRefCnt { public: - GraphicsOperationCollection(const IntRect& drawArea); + GraphicsOperationCollection(); ~GraphicsOperationCollection(); void apply(PlatformGraphicsContext* context); @@ -48,13 +48,12 @@ public: bool isEmpty(); private: - IntRect m_drawArea; Vector<GraphicsOperation::Operation*> m_operations; }; class AutoGraphicsOperationCollection { public: - AutoGraphicsOperationCollection(const IntRect& area); + AutoGraphicsOperationCollection(); ~AutoGraphicsOperationCollection(); GraphicsContext* context() { return m_graphicsContext; } GraphicsOperationCollection* picture() { return m_graphicsOperationCollection; } diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp index ce9ce5a..3b37693 100644 --- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp @@ -82,6 +82,8 @@ static bool setBitmapDash(SkPaint* paint, int width) { s->setLocalMatrix(matrix); paint->setShader(s)->unref(); + paint->setFilterBitmap(true); + paint->setAntiAlias(true); return true; } diff --git a/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp index 7bed5bb..d59674b 100644 --- a/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp @@ -45,6 +45,7 @@ #include "SkTypeface.h" #include "SkUtils.h" #include "TextRun.h" +#include "SkTypeface_android.h" #ifdef SUPPORT_COMPLEX_SCRIPTS #include "HarfbuzzSkia.h" @@ -461,26 +462,8 @@ public: } private: - enum CustomScript { - Bengali, - Devanagari, - Hebrew, - HebrewBold, - Kannada, - Malayalam, - Naskh, - Tamil, - TamilBold, - Telugu, - Thai, - NUM_SCRIPTS - }; - - static const char* paths[NUM_SCRIPTS]; - void setupFontForScriptRun(); - const FontPlatformData* setupComplexFont(CustomScript script, - const FontPlatformData& platformData); + const FontPlatformData* setupComplexFont(HB_Script script, const FontPlatformData& platformData); HB_FontRec* allocHarfbuzzFont(); void deleteGlyphArrays(); void createGlyphArrays(int); @@ -522,22 +505,6 @@ private: unsigned m_letterSpacing; // pixels to be added after each glyph. }; - -// Indexed using enum CustomScript -const char* TextRunWalker::paths[] = { - "/system/fonts/Lohit-Bengali.ttf", - "/system/fonts/DroidSansDevanagari-Regular.ttf", - "/system/fonts/DroidSansHebrew-Regular.ttf", - "/system/fonts/DroidSansHebrew-Bold.ttf", - "/system/fonts/Lohit-Kannada.ttf", - "/system/fonts/AnjaliNewLipi-light.ttf", - "/system/fonts/DroidNaskh-Regular.ttf", - "/system/fonts/DroidSansTamil-Regular.ttf", - "/system/fonts/DroidSansTamil-Bold.ttf", - "/system/fonts/Lohit-Telugu.ttf", - "/system/fonts/DroidSansThai.ttf" -}; - TextRunWalker::TextRunWalker(const TextRun& run, int startingX, int startingY, const Font* font) : m_font(font) , m_startingX(startingX) @@ -692,8 +659,7 @@ void TextRunWalker::setWordAndLetterSpacing(int wordSpacingAdjustment, } const FontPlatformData* TextRunWalker::setupComplexFont( - CustomScript script, - const FontPlatformData& platformData) + HB_Script script, const FontPlatformData& platformData) { static FallbackHash fallbackPlatformData; @@ -703,15 +669,19 @@ const FontPlatformData* TextRunWalker::setupComplexFont( // italic, then bold italic. additional fake style bits can be added. int scriptStyleIndex = script; if (platformData.isFakeBold()) - scriptStyleIndex += NUM_SCRIPTS; + scriptStyleIndex += HB_ScriptCount; if (platformData.isFakeItalic()) - scriptStyleIndex += NUM_SCRIPTS << 1; + scriptStyleIndex += HB_ScriptCount << 1; FallbackFontKey key(scriptStyleIndex, platformData.size()); FontPlatformData* newPlatformData = 0; if (!fallbackPlatformData.contains(key)) { - SkTypeface* typeface = SkTypeface::CreateFromFile(paths[script]); + SkTypeface::Style currentStyle = SkTypeface::kNormal; + if (platformData.typeface()) + currentStyle = platformData.typeface()->style(); + SkTypeface* typeface = SkCreateTypefaceForScript(script, currentStyle, + SkPaint::kElegant_Variant); newPlatformData = new FontPlatformData(platformData, typeface); SkSafeUnref(typeface); fallbackPlatformData.set(key, newPlatformData); @@ -729,61 +699,8 @@ void TextRunWalker::setupFontForScriptRun() const FontData* fontData = m_font->glyphDataForCharacter(m_run[0], false).fontData; const FontPlatformData& platformData = fontData->fontDataForCharacter(' ')->platformData(); - const FontPlatformData* complexPlatformData = &platformData; - - switch (m_item.item.script) { - case HB_Script_Bengali: - complexPlatformData = setupComplexFont(Bengali, platformData); - break; - case HB_Script_Devanagari: - complexPlatformData = setupComplexFont(Devanagari, platformData); - break; - case HB_Script_Hebrew: - switch (platformData.typeface()->style()) { - case SkTypeface::kBold: - case SkTypeface::kBoldItalic: - complexPlatformData = setupComplexFont(HebrewBold, platformData); - break; - case SkTypeface::kNormal: - case SkTypeface::kItalic: - default: - complexPlatformData = setupComplexFont(Hebrew, platformData); - break; - } - break; - case HB_Script_Kannada: - complexPlatformData = setupComplexFont(Kannada, platformData); - break; - case HB_Script_Malayalam: - complexPlatformData = setupComplexFont(Malayalam, platformData); - break; - case HB_Script_Arabic: - complexPlatformData = setupComplexFont(Naskh, platformData); - break; - case HB_Script_Tamil: - switch (platformData.typeface()->style()) { - case SkTypeface::kBold: - case SkTypeface::kBoldItalic: - complexPlatformData = setupComplexFont(TamilBold, platformData); - break; - case SkTypeface::kNormal: - case SkTypeface::kItalic: - default: - complexPlatformData = setupComplexFont(Tamil, platformData); - break; - } - break; - case HB_Script_Telugu: - complexPlatformData = setupComplexFont(Telugu, platformData); - break; - case HB_Script_Thai: - complexPlatformData = setupComplexFont(Thai, platformData); - break; - default: - // HB_Script_Common; includes Ethiopic - complexPlatformData = &platformData; - break; - } + const FontPlatformData* complexPlatformData = setupComplexFont(m_item.item.script, platformData); + m_item.face = complexPlatformData->harfbuzzFace(); m_item.font->userData = const_cast<FontPlatformData*>(complexPlatformData); diff --git a/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp b/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp index 5551965..d827c44 100644 --- a/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp +++ b/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp @@ -3,79 +3,87 @@ #if USE(ACCELERATED_COMPOSITING) +#define WRITE_VAL(format, ...) (snprintf(m_valueBuffer, BUF_SIZE, format, __VA_ARGS__), writeEntry(label, m_valueBuffer)) + namespace WebCore { -void lwrite(FILE* file, const char* str) +void LayerDumper::writeIntVal(const char* label, int value) { - fwrite(str, sizeof(char), strlen(str), file); + WRITE_VAL("%d", value); } -void writeIndent(FILE* file, int indentLevel) +void LayerDumper::writeHexVal(const char* label, int value) { - if (indentLevel) - fprintf(file, "%*s", indentLevel*2, " "); + WRITE_VAL("%x", value); } -void writeln(FILE* file, int indentLevel, const char* str) +void LayerDumper::writeFloatVal(const char* label, float value) { - writeIndent(file, indentLevel); - lwrite(file, str); - lwrite(file, "\n"); + WRITE_VAL("%.3f", value); } -void writeIntVal(FILE* file, int indentLevel, const char* str, int value) +void LayerDumper::writePoint(const char* label, SkPoint point) { - writeIndent(file, indentLevel); - fprintf(file, "%s = %d;\n", str, value); + WRITE_VAL("{ x = %.3f; y = %.3f; }", point.fX, point.fY); } -void writeHexVal(FILE* file, int indentLevel, const char* str, int value) +void LayerDumper::writeIntPoint(const char* label, IntPoint point) { - writeIndent(file, indentLevel); - fprintf(file, "%s = %x;\n", str, value); + WRITE_VAL("{ x = %d; y = %d; }", point.x(), point.y()); } -void writeFloatVal(FILE* file, int indentLevel, const char* str, float value) +void LayerDumper::writeSize(const char* label, SkSize size) { - writeIndent(file, indentLevel); - fprintf(file, "%s = %.3f;\n", str, value); + WRITE_VAL("{ w = %.3f; h = %.3f; }", size.width(), size.height()); } -void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point) +void LayerDumper::writeRect(const char* label, SkRect rect) { - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY); + WRITE_VAL("{ x = %.3f; y = %.3f; w = %.3f; h = %.3f; }", + rect.fLeft, rect.fTop, rect.width(), rect.height()); } -void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point) +void LayerDumper::writeMatrix(const char* label, const TransformationMatrix& matrix) { - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %d; y = %d; };\n", str, point.x(), point.y()); + WRITE_VAL("{ (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f)," + "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) }", + matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(), + matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(), + matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(), + matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()); } -void writeSize(FILE* file, int indentLevel, const char* str, SkSize size) +void LayerDumper::writeLength(const char* label, SkLength value) { - writeIndent(file, indentLevel); - fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height()); + if (value.defined()) + WRITE_VAL("{ type = %d; value = %.2f; }", value.type, value.value); + else + writeEntry(label, "<undefined>"); } -void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect) +void FileLayerDumper::beginLayer(const char* className, const LayerAndroid* layerPtr) { - writeIndent(file, indentLevel); - fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n", - str, rect.fLeft, rect.fTop, rect.width(), rect.height()); + LayerDumper::beginLayer(className, layerPtr); + writeLine("{"); + writeHexVal("layer", (int)layerPtr); } -void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix) +void FileLayerDumper::endLayer() { - writeIndent(file, indentLevel); - fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f)," - "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n", - str, - matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(), - matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(), - matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(), - matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44()); + writeLine("}"); + LayerDumper::endLayer(); +} + +void FileLayerDumper::writeEntry(const char* label, const char* value) +{ + fprintf(m_file, "%*s%s = %s\n", (m_indentLevel + 1) * 2, " ", label, value); +} + +void FileLayerDumper::writeLine(const char* str) +{ + if (m_indentLevel) + fprintf(m_file, "%*s", m_indentLevel * 2, " "); + fprintf(m_file, "%s\n", str); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/layers/DumpLayer.h b/Source/WebCore/platform/graphics/android/layers/DumpLayer.h index 5b30952..9fd3365 100644 --- a/Source/WebCore/platform/graphics/android/layers/DumpLayer.h +++ b/Source/WebCore/platform/graphics/android/layers/DumpLayer.h @@ -17,7 +17,9 @@ #ifndef DumpLayer_h #define DumpLayer_h +#include "FixedPositioning.h" #include "IntPoint.h" +#include "LayerAndroid.h" #include "SkPoint.h" #include "SkRect.h" #include "SkSize.h" @@ -50,17 +52,59 @@ namespace WebCore { -void lwrite(FILE* file, const char* str); -void writeIndent(FILE* file, int indentLevel); -void writeln(FILE* file, int indentLevel, const char* str); -void writeIntVal(FILE* file, int indentLevel, const char* str, int value); -void writeHexVal(FILE* file, int indentLevel, const char* str, int value); -void writeFloatVal(FILE* file, int indentLevel, const char* str, float value); -void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point); -void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point); -void writeSize(FILE* file, int indentLevel, const char* str, SkSize size); -void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect); -void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix); +class LayerDumper { +public: + LayerDumper(int initialIndentLevel = 0) + : m_indentLevel(initialIndentLevel) + {} + virtual ~LayerDumper() {} + + virtual void beginLayer(const char* className, const LayerAndroid* layerPtr) {} + + virtual void endLayer() {} + + virtual void beginChildren(int childCount) { + m_indentLevel++; + } + virtual void endChildren() { + m_indentLevel--; + } + + void writeIntVal(const char* label, int value); + void writeHexVal(const char* label, int value); + void writeFloatVal(const char* label, float value); + void writePoint(const char* label, SkPoint value); + void writeIntPoint(const char* label, IntPoint value); + void writeSize(const char* label, SkSize value); + void writeRect(const char* label, SkRect value); + void writeMatrix(const char* label, const TransformationMatrix& value); + void writeLength(const char* label, SkLength value); + +protected: + virtual void writeEntry(const char* label, const char* value) = 0; + + int m_indentLevel; + +private: + static const int BUF_SIZE = 4096; + char m_valueBuffer[BUF_SIZE]; +}; + +class FileLayerDumper : public LayerDumper { +public: + FileLayerDumper(FILE* file) + : m_file(file) + {} + + virtual void beginLayer(const char* className, const LayerAndroid* layerPtr); + virtual void endLayer(); +protected: + virtual void writeEntry(const char* label, const char* value); + +private: + void writeLine(const char* str); + FILE* m_file; +}; } diff --git a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp index 82afe8f..aa204f8 100644 --- a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp +++ b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp @@ -86,25 +86,17 @@ void FixedPositioning::contentDraw(SkCanvas* canvas, Layer::PaintStyle style) } } -void writeLength(FILE* file, int indentLevel, const char* str, SkLength length) +void FixedPositioning::dumpLayer(LayerDumper* dumper) const { - if (!length.defined()) - return; - writeIndent(file, indentLevel); - fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value); -} - -void FixedPositioning::dumpLayer(FILE* file, int indentLevel) const -{ - writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft); - writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop); - writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight); - writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom); - writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft); - writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop); - writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight); - writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom); - writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect); + dumper->writeLength("fixedLeft", m_fixedLeft); + dumper->writeLength("fixedTop", m_fixedTop); + dumper->writeLength("fixedRight", m_fixedRight); + dumper->writeLength("fixedBottom", m_fixedBottom); + dumper->writeLength("fixedMarginLeft", m_fixedMarginLeft); + dumper->writeLength("fixedMarginTop", m_fixedMarginTop); + dumper->writeLength("fixedMarginRight", m_fixedMarginRight); + dumper->writeLength("fixedMarginBottom", m_fixedMarginBottom); + dumper->writeRect("fixedRect", m_fixedRect); } BackgroundImagePositioning::BackgroundImagePositioning(LayerAndroid* layer, const BackgroundImagePositioning& position) diff --git a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h index e273a25..ac838c8 100644 --- a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h +++ b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h @@ -130,7 +130,7 @@ public: void contentDraw(SkCanvas* canvas, Layer::PaintStyle style); - void dumpLayer(FILE*, int indentLevel) const; + void dumpLayer(LayerDumper*) const; // ViewStateSerializer friends friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp index 3532542..4481f55 100644 --- a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp @@ -29,10 +29,10 @@ IFrameLayerAndroid* IFrameLayerAndroid::updatePosition(SkRect viewport, return this; } -void IFrameLayerAndroid::dumpLayer(FILE* file, int indentLevel) const +void IFrameLayerAndroid::dumpLayer(LayerDumper* dumper) const { - writeIntVal(file, indentLevel + 1, "m_isIframe", true); - writeIntPoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset); + LayerAndroid::dumpLayer(dumper); + dumper->writeIntPoint("m_iframeOffset", m_iframeOffset); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h index f2fbf49..08e7212 100644 --- a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h @@ -53,7 +53,7 @@ public: virtual IFrameLayerAndroid* updatePosition(SkRect viewport, IFrameLayerAndroid* parentIframeLayer); - virtual void dumpLayer(FILE*, int indentLevel) const; + virtual void dumpLayer(LayerDumper*) const; const IntPoint& iframeOffset() const { return m_iframeOffset; } diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp index 228a30e..438d96c 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp @@ -601,7 +601,7 @@ void LayerAndroid::showLayer(int indent) m_clippingRect.width(), m_clippingRect.height()); ALOGD("%s s:%x %s %s (%d) [%d:%x - 0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) " "clip (%d, %d, %d, %d) %s %s m_content(%x), pic w: %d h: %d originalLayer: %x %d", - spaces, m_surface, m_haveClip ? "CLIP LAYER" : "", subclassName().ascii().data(), + spaces, m_surface, m_haveClip ? "CLIP LAYER" : "", subclassName(), subclassType(), uniqueId(), this, m_owningLayer, needsTexture() ? "needsTexture" : "", m_imageCRC ? "hasImage" : "", @@ -954,60 +954,42 @@ void LayerAndroid::setFixedPosition(FixedPositioning* position) { m_fixedPosition = position; } -void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const +void LayerAndroid::dumpLayer(LayerDumper* dumper) const { - writeHexVal(file, indentLevel + 1, "layer", (int)this); - writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId); - writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip); - writeIntVal(file, indentLevel + 1, "isFixed", isPositionFixed()); + dumper->writeIntVal("layerId", m_uniqueId); + dumper->writeIntVal("haveClip", m_haveClip); + dumper->writeIntVal("isFixed", isPositionFixed()); - writeFloatVal(file, indentLevel + 1, "opacity", getOpacity()); - writeSize(file, indentLevel + 1, "size", getSize()); - writePoint(file, indentLevel + 1, "position", getPosition()); - writePoint(file, indentLevel + 1, "anchor", getAnchorPoint()); + dumper->writeFloatVal("opacity", getOpacity()); + dumper->writeSize("size", getSize()); + dumper->writePoint("position", getPosition()); + dumper->writePoint("anchor", getAnchorPoint()); - writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform); - writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform); - writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect)); + dumper->writeMatrix("drawMatrix", m_drawTransform); + dumper->writeMatrix("transformMatrix", m_transform); + dumper->writeRect("clippingRect", SkRect(m_clippingRect)); if (m_content) { - writeIntVal(file, indentLevel + 1, "m_content.width", m_content->width()); - writeIntVal(file, indentLevel + 1, "m_content.height", m_content->height()); + dumper->writeIntVal("m_content.width", m_content->width()); + dumper->writeIntVal("m_content.height", m_content->height()); } if (m_fixedPosition) - return m_fixedPosition->dumpLayer(file, indentLevel); + m_fixedPosition->dumpLayer(dumper); } -void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const +void LayerAndroid::dumpLayers(LayerDumper* dumper) const { - writeln(file, indentLevel, "{"); - - dumpLayer(file, indentLevel); + dumper->beginLayer(subclassName(), this); + dumpLayer(dumper); + dumper->beginChildren(countChildren()); if (countChildren()) { - writeln(file, indentLevel + 1, "children = ["); - for (int i = 0; i < countChildren(); i++) { - if (i > 0) - writeln(file, indentLevel + 1, ", "); - getChild(i)->dumpLayers(file, indentLevel + 1); - } - writeln(file, indentLevel + 1, "];"); + for (int i = 0; i < countChildren(); i++) + getChild(i)->dumpLayers(dumper); } - writeln(file, indentLevel, "}"); -} - -void LayerAndroid::dumpToLog() const -{ - FILE* file = fopen("/data/data/com.android.browser/layertmp", "w"); - dumpLayers(file, 0); - fclose(file); - file = fopen("/data/data/com.android.browser/layertmp", "r"); - char buffer[512]; - bzero(buffer, sizeof(buffer)); - while (fgets(buffer, sizeof(buffer), file)) - SkDebugf("%s", buffer); - fclose(file); + dumper->endChildren(); + dumper->endLayer(); } LayerAndroid* LayerAndroid::findById(int match) diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h index 41f6420..b28daef 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h @@ -73,6 +73,7 @@ class IFrameLayerAndroid; class LayerMergeState; class RenderLayer; class PaintedSurface; +class LayerDumper; class TexturesResult { public: @@ -100,7 +101,7 @@ public: CanvasLayer, BaseLayer } SubclassType; typedef enum { InvalidateNone = 0, InvalidateLayers } InvalidateFlags; - String subclassName() + const char* subclassName() const { switch (subclassType()) { case LayerAndroid::StandardLayer: @@ -195,9 +196,7 @@ public: bool hasAnimations() const; void addDirtyArea(); - virtual void dumpLayer(FILE*, int indentLevel) const; - void dumpLayers(FILE*, int indentLevel) const; - void dumpToLog() const; + void dumpLayers(LayerDumper*) const; virtual IFrameLayerAndroid* updatePosition(SkRect viewport, IFrameLayerAndroid* parentIframeLayer); @@ -292,6 +291,7 @@ public: } protected: + virtual void dumpLayer(LayerDumper*) const; /** Call this with the current viewport (scrolling, zoom) to update the position of the fixed layers. diff --git a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp index 4398146..f012c42 100644 --- a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp +++ b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp @@ -1,6 +1,10 @@ +#define LOG_TAG "PictureLayerContent" +#define LOG_NDEBUG 1 + #include "config.h" #include "PictureLayerContent.h" +#include "AndroidLog.h" #include "InspectorCanvas.h" #include "SkPicture.h" @@ -90,6 +94,7 @@ void PictureLayerContent::draw(SkCanvas* canvas) if (!m_picture) return; + TRACE_METHOD(); android::Mutex::Autolock lock(m_drawLock); SkRect r = SkRect::MakeWH(width(), height()); canvas->clipRect(r); diff --git a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp index b648e72..5d516af 100644 --- a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp +++ b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp @@ -1,6 +1,10 @@ +#define LOG_TAG "PicturePileLayerContent" +#define LOG_NDEBUG 1 + #include "config.h" #include "PicturePileLayerContent.h" +#include "AndroidLog.h" #include "SkCanvas.h" #include "SkPicture.h" @@ -13,6 +17,7 @@ PicturePileLayerContent::PicturePileLayerContent(const PicturePile& picturePile) void PicturePileLayerContent::draw(SkCanvas* canvas) { + TRACE_METHOD(); android::Mutex::Autolock lock(m_drawLock); m_picturePile.draw(canvas); } diff --git a/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp index bfa0789..a68c01a 100644 --- a/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp @@ -384,6 +384,7 @@ bool GLUtils::isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor) // If the bitmap is the pure color, skip the transfer step, and update the Tile Info. // This check is taking < 1ms if we do full bitmap check per tile. // TODO: use the SkPicture to determine whether or not a tile is single color. + TRACE_METHOD(); pureColor = Color(Color::transparent); bitmap.lockPixels(); bool sameColor = true; @@ -483,6 +484,7 @@ void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBi bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap) { + TRACE_METHOD(); SkAutoLockPixels alp(bitmap); if (!bitmap.getPixels()) return false; diff --git a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp index 3fcbdb2..c1b91a3 100644 --- a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp @@ -79,12 +79,12 @@ bool PaintTileOperation::operator==(const QueuedOperation* operation) return op->m_tile == m_tile; } -void PaintTileOperation::run() +void PaintTileOperation::run(BaseRenderer* renderer) { TRACE_METHOD(); if (m_tile) { - m_tile->paintBitmap(m_painter); + m_tile->paintBitmap(m_painter, renderer); m_tile->setRepaintPending(false); m_tile = 0; } diff --git a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h index c82cdcd..ecd3ce9 100644 --- a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h +++ b/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h @@ -42,7 +42,7 @@ public: GLWebViewState* state, bool isLowResPrefetch); virtual ~PaintTileOperation(); virtual bool operator==(const QueuedOperation* operation); - virtual void run(); + virtual void run(BaseRenderer* renderer); virtual void* uniquePtr() { return m_tile; } // returns a rendering priority for m_tile, lower values are processed faster virtual int priority(); diff --git a/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h b/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h index 7625528..fe6f8a3 100644 --- a/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h +++ b/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h @@ -28,10 +28,12 @@ namespace WebCore { +class BaseRenderer; + class QueuedOperation { public: virtual ~QueuedOperation() {} - virtual void run() = 0; + virtual void run(BaseRenderer* renderer) = 0; virtual bool operator==(const QueuedOperation* operation) = 0; virtual void* uniquePtr() = 0; virtual int priority() = 0; diff --git a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp index 47e5c17..a67a890 100644 --- a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp @@ -42,20 +42,17 @@ namespace WebCore { -SkBitmap* RasterRenderer::g_bitmap = 0; - -RasterRenderer::RasterRenderer() : BaseRenderer(BaseRenderer::Raster) +RasterRenderer::RasterRenderer() + : BaseRenderer(BaseRenderer::Raster) + , m_bitmapIsPureColor(false) { + m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, + TilesManager::instance()->tileWidth(), + TilesManager::instance()->tileHeight()); + m_bitmap.allocPixels(); #ifdef DEBUG_COUNT ClassTracker::instance()->increment("RasterRenderer"); #endif - if (!g_bitmap) { - g_bitmap = new SkBitmap(); - g_bitmap->setConfig(SkBitmap::kARGB_8888_Config, - TilesManager::instance()->tileWidth(), - TilesManager::instance()->tileHeight()); - g_bitmap->allocPixels(); - } } RasterRenderer::~RasterRenderer() @@ -67,9 +64,14 @@ RasterRenderer::~RasterRenderer() void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) { + TRACE_METHOD(); + if (renderInfo.baseTile->isLayerTile()) { - g_bitmap->setIsOpaque(false); - g_bitmap->eraseARGB(0, 0, 0, 0); + m_bitmap.setIsOpaque(false); + + // clear bitmap if necessary + if (!m_bitmapIsPureColor || m_bitmapPureColor != Color::transparent) + m_bitmap.eraseARGB(0, 0, 0, 0); } else { Color defaultBackground = Color::white; Color* background = renderInfo.tilePainter->background(); @@ -78,12 +80,15 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can background = &defaultBackground; } ALOGV("setupCanvas use background on Base Layer %x", background->rgb()); - g_bitmap->setIsOpaque(!background->hasAlpha()); - g_bitmap->eraseARGB(background->alpha(), background->red(), - background->green(), background->blue()); + m_bitmap.setIsOpaque(!background->hasAlpha()); + + // fill background color if necessary + if (!m_bitmapIsPureColor || m_bitmapPureColor != *background) + m_bitmap.eraseARGB(background->alpha(), background->red(), + background->green(), background->blue()); } - SkDevice* device = new SkDevice(*g_bitmap); + SkDevice* device = new SkDevice(m_bitmap); canvas->setDevice(device); @@ -92,14 +97,15 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can void RasterRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) { - const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); - GLUtils::paintTextureWithBitmap(&renderInfo, bitmap); + GLUtils::paintTextureWithBitmap(&renderInfo, m_bitmap); } void RasterRenderer::checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) { - const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); - renderInfo.isPureColor = GLUtils::isPureColorBitmap(bitmap, renderInfo.pureColor); + m_bitmapIsPureColor = GLUtils::isPureColorBitmap(m_bitmap, m_bitmapPureColor); + + renderInfo.isPureColor = m_bitmapIsPureColor; + renderInfo.pureColor = m_bitmapPureColor; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h index 39e00f2..34b57ca 100644 --- a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h +++ b/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h @@ -46,14 +46,14 @@ public: ~RasterRenderer(); protected: - virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas); private: - static SkBitmap* g_bitmap; - + SkBitmap m_bitmap; + bool m_bitmapIsPureColor; + Color m_bitmapPureColor; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp index 1898910..96a4a16 100644 --- a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp @@ -218,7 +218,7 @@ void Surface::prepareGL(bool layerTilesDisabled, bool updateWithBlit) ALOGV("prepareGL on Surf %p with SurfBack %p, %d layers, first layer %s (%d) " "prepareArea(%d, %d - %d x %d) fullArea(%d, %d - %d x %d)", this, m_surfaceBacking, m_layers.size(), - getFirstLayer()->subclassName().ascii().data(), + getFirstLayer()->subclassName(), getFirstLayer()->uniqueId(), prepareArea.x(), prepareArea.y(), prepareArea.width(), prepareArea.height(), fullArea.x(), fullArea.y(), fullArea.width(), fullArea.height()); @@ -253,7 +253,7 @@ bool Surface::drawGL(bool layerTilesDisabled) bool askRedraw = false; if (m_surfaceBacking && !tilesDisabled) { ALOGV("drawGL on Surf %p with SurfBack %p, first layer %s (%d)", this, m_surfaceBacking, - getFirstLayer()->subclassName().ascii().data(), getFirstLayer()->uniqueId()); + getFirstLayer()->subclassName(), getFirstLayer()->uniqueId()); bool force3dContentVisible = true; IntRect drawArea = visibleContentArea(force3dContentVisible); diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp index 174720f..1270498 100644 --- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp @@ -38,6 +38,10 @@ namespace WebCore { using namespace android::uirenderer; +// Tag used to display current number of SurfaceCollections. +// Note: this will only work if one webview is actively drawing at a time. +static const char* COLLECTION_COUNT_TAG = "CollectionCount"; + SurfaceCollectionManager::SurfaceCollectionManager() : m_drawingCollection(0) , m_paintingCollection(0) @@ -87,6 +91,12 @@ void SurfaceCollectionManager::swap() m_paintingCollection = m_queuedCollection; m_queuedCollection = 0; + if (ATRACE_ENABLED()) { + ATRACE_INT(COLLECTION_COUNT_TAG, + (m_drawingCollection ? 1 : 0) + + (m_paintingCollection ? 1 : 0)); + } + ALOGV("SWAPPING COMPLETE, D %p, P %p, Q %p", m_drawingCollection, m_paintingCollection, m_queuedCollection); } @@ -106,6 +116,8 @@ void SurfaceCollectionManager::clearCollections() m_paintingCollection = 0; SkSafeUnref(m_queuedCollection); m_queuedCollection = 0; + + ATRACE_INT(COLLECTION_COUNT_TAG, 0); } void SurfaceCollectionManager::updatePaintingCollection(SurfaceCollection* newCollection) @@ -126,8 +138,10 @@ bool SurfaceCollectionManager::updateWithSurfaceCollection(SurfaceCollection* ne if (!newCollection || brandNew) { clearCollections(); - if (brandNew) + if (brandNew) { updatePaintingCollection(newCollection); + ATRACE_INT(COLLECTION_COUNT_TAG, 1); + } return false; } @@ -157,6 +171,13 @@ bool SurfaceCollectionManager::updateWithSurfaceCollection(SurfaceCollection* ne // don't have painting collection, paint this one! updatePaintingCollection(newCollection); } + + if (ATRACE_ENABLED()) { + ATRACE_INT(COLLECTION_COUNT_TAG, + (m_drawingCollection ? 1 : 0) + + (m_paintingCollection ? 1 : 0) + + (m_queuedCollection ? 1 : 0)); + } return m_drawingCollection && TilesManager::instance()->useDoubleBuffering(); } @@ -225,12 +246,12 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, int returnFlags = 0; bool didCollectionSwap = false; + bool tryFastBlit = !m_fastSwapMode; if (m_paintingCollection) { ALOGV("preparing painting collection %p", m_paintingCollection); m_paintingCollection->evaluateAnimations(currentTime); - bool tryFastBlit = !m_fastSwapMode; m_paintingCollection->prepareGL(visibleContentRect, tryFastBlit); m_paintingCollection->computeTexturesAmount(texturesResultPtr); @@ -261,6 +282,9 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, && m_drawingCollection->isReady())) { // either a swap just occurred, or there is no more work to be done: do a full draw m_drawingCollection->swapTiles(); + + if (didCollectionSwap && m_paintingCollection) + m_paintingCollection->prepareGL(visibleContentRect, tryFastBlit); returnFlags |= DrawGlInfo::kStatusDraw; } else { // current collection not ready - invoke functor in process mode @@ -286,6 +310,9 @@ int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect, if (didCollectionSwap || m_fastSwapMode || (drawingReady && !m_paintingCollection)) m_drawingCollection->swapTiles(); + if (didCollectionSwap && m_paintingCollection) + m_paintingCollection->prepareGL(visibleContentRect, tryFastBlit); + if (drawingReady) { // exit fast swap mode, as content is up to date m_fastSwapMode = false; diff --git a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp index cc94c9c..74e663a 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp @@ -32,6 +32,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "AndroidLog.h" +#include "BaseRenderer.h" #include "GLUtils.h" #include "PaintTileOperation.h" #include "TilesManager.h" @@ -39,6 +40,19 @@ namespace WebCore { +TexturesGenerator::TexturesGenerator(TilesManager* instance) + : Thread(false) + , m_tilesManager(instance) + , m_deferredMode(false) + , m_renderer(0) +{ +} + +TexturesGenerator::~TexturesGenerator() +{ + delete m_renderer; +} + bool TexturesGenerator::tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter) { android::Mutex::Autolock lock(mRequestedOperationsLock); @@ -83,12 +97,11 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) i++; } } - delete filter; } status_t TexturesGenerator::readyToRun() { - ALOGV("Thread ready to run"); + m_renderer = BaseRenderer::createRenderer(); return NO_ERROR; } @@ -165,7 +178,9 @@ bool TexturesGenerator::threadLoop() if (currentOperation) { ALOGV("threadLoop, painting the request with priority %d", currentOperation->priority()); - currentOperation->run(); + // swap out the renderer if necessary + BaseRenderer::swapRendererIfNeeded(m_renderer); + currentOperation->run(m_renderer); } mRequestedOperationsLock.lock(); diff --git a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h index 290ad08..2998330 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h +++ b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h @@ -29,7 +29,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "QueuedOperation.h" -#include "TilePainter.h" +#include "TransferQueue.h" #include <wtf/HashMap.h> #include <wtf/Vector.h> @@ -43,10 +43,9 @@ class TilesManager; class TexturesGenerator : public Thread { public: - TexturesGenerator(TilesManager* instance) : Thread(false) - , m_tilesManager(instance) - , m_deferredMode(false) { } - virtual ~TexturesGenerator() { } + TexturesGenerator(TilesManager* instance); + virtual ~TexturesGenerator(); + virtual status_t readyToRun(); bool tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter); @@ -68,6 +67,7 @@ private: android::Condition mRequestedOperationsCond; TilesManager* m_tilesManager; + BaseRenderer* m_renderer; bool m_deferredMode; // defer painting for one second if best in queue has priority diff --git a/Source/WebCore/platform/graphics/android/rendering/Tile.cpp b/Source/WebCore/platform/graphics/android/rendering/Tile.cpp index 96b189a..76be981 100644 --- a/Source/WebCore/platform/graphics/android/rendering/Tile.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/Tile.cpp @@ -33,7 +33,7 @@ #include "AndroidLog.h" #include "GLUtils.h" -#include "RasterRenderer.h" +#include "BaseRenderer.h" #include "TextureInfo.h" #include "TileTexture.h" #include "TilesManager.h" @@ -64,7 +64,6 @@ Tile::Tile(bool isLayerTile) #ifdef DEBUG_COUNT ClassTracker::instance()->increment("Tile"); #endif - m_renderer = BaseRenderer::createRenderer(); } Tile::~Tile() @@ -74,8 +73,6 @@ Tile::~Tile() if (m_frontTexture) m_frontTexture->release(this); - delete m_renderer; - #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("Tile"); #endif @@ -297,7 +294,7 @@ bool Tile::isTileVisible(const IntRect& viewTileBounds) } // This is called from the texture generation thread -void Tile::paintBitmap(TilePainter* painter) +void Tile::paintBitmap(TilePainter* painter, BaseRenderer* renderer) { // We acquire the values below atomically. This ensures that we are reading // values correctly across cores. Further, once we have these values they @@ -328,8 +325,6 @@ void Tile::paintBitmap(TilePainter* painter) return; } - // swap out the renderer if necessary - BaseRenderer::swapRendererIfNeeded(m_renderer); // setup the common renderInfo fields; TileRenderInfo renderInfo; renderInfo.x = x; @@ -343,7 +338,7 @@ void Tile::paintBitmap(TilePainter* painter) const float tileWidth = renderInfo.tileSize.width(); const float tileHeight = renderInfo.tileSize.height(); - m_renderer->renderTiledContent(renderInfo); + renderer->renderTiledContent(renderInfo); m_atomicSync.lock(); diff --git a/Source/WebCore/platform/graphics/android/rendering/Tile.h b/Source/WebCore/platform/graphics/android/rendering/Tile.h index b045f1f..f467bb0 100644 --- a/Source/WebCore/platform/graphics/android/rendering/Tile.h +++ b/Source/WebCore/platform/graphics/android/rendering/Tile.h @@ -28,7 +28,6 @@ #if USE(ACCELERATED_COMPOSITING) -#include "BaseRenderer.h" #include "FloatPoint.h" #include "SkRect.h" #include "SkRegion.h" @@ -39,9 +38,10 @@ namespace WebCore { +class BaseRenderer; +class GLWebViewState; class TextureInfo; class TileTexture; -class GLWebViewState; /** * An individual tile that is used to construct part of a webpage's BaseLayer of @@ -107,7 +107,7 @@ public: const FloatRect& fillPortion); // the only thread-safe function called by the background thread - void paintBitmap(TilePainter* painter); + void paintBitmap(TilePainter* painter, BaseRenderer* renderer); bool intersectWithRect(int x, int y, int tileWidth, int tileHeight, float scale, const SkRect& dirtyRect, @@ -171,8 +171,6 @@ private: // across all threads and cores. android::Mutex m_atomicSync; - BaseRenderer* m_renderer; - bool m_isLayerTile; // the most recent GL draw before this tile was prepared. used for diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp index 0b4ba7b..e584b81 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp @@ -65,6 +65,10 @@ #define LAYER_TEXTURES_DESTROY_TIMEOUT 60 // If we do not need layers for 60 seconds, free the textures +// Eventually this should be dynamically be determined, and smart scheduling +// between the generators should be implemented +#define NUM_TEXTURES_GENERATORS 1 + namespace WebCore { int TilesManager::getMaxTextureAllocation() @@ -105,10 +109,21 @@ TilesManager::TilesManager() m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); - m_pixmapsGenerationThread = new TexturesGenerator(this); - m_pixmapsGenerationThread->run("TexturesGenerator"); + + m_textureGenerators = new sp<TexturesGenerator>[NUM_TEXTURES_GENERATORS]; + for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++) { + m_textureGenerators[i] = new TexturesGenerator(this); + ALOGD("Starting TG #%d, %p", i, m_textureGenerators[i].get()); + m_textureGenerators[i]->run("TexturesGenerator"); + } } +TilesManager::~TilesManager() +{ + delete[] m_textureGenerators; +} + + void TilesManager::allocateTextures() { int nbTexturesToAllocate = m_currentTextureCount - m_textures.size(); @@ -488,6 +503,29 @@ void TilesManager::updateTilesIfContextVerified() return; } +void TilesManager::removeOperationsForFilter(OperationFilter* filter) +{ + for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++) + m_textureGenerators[i]->removeOperationsForFilter(filter); + delete filter; +} + +bool TilesManager::tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter) +{ + for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++) { + if (m_textureGenerators[i]->tryUpdateOperationWithPainter(tile, painter)) + return true; + } + return false; +} + +void TilesManager::scheduleOperation(QueuedOperation* operation) +{ + // TODO: painter awareness, store prefer awareness, store preferred thread into painter + m_scheduleThread = (m_scheduleThread + 1) % NUM_TEXTURES_GENERATORS; + m_textureGenerators[m_scheduleThread]->scheduleOperation(operation); +} + int TilesManager::tileWidth() { return TILE_WIDTH; diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.h b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h index f0d2eac..0781ef6 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h @@ -53,23 +53,9 @@ public: return gInstance != 0; } - void removeOperationsForFilter(OperationFilter* filter) - { - m_pixmapsGenerationThread->removeOperationsForFilter(filter); - } - - bool tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter) - { - return m_pixmapsGenerationThread->tryUpdateOperationWithPainter(tile, painter); - } - - void scheduleOperation(QueuedOperation* operation) - { - m_pixmapsGenerationThread->scheduleOperation(operation); - } - ShaderProgram* shader() { return &m_shader; } TransferQueue* transferQueue(); + VideoLayerManager* videoLayerManager() { return &m_videoLayerManager; } void updateTilesIfContextVerified(); @@ -165,8 +151,15 @@ public: return m_drawGLCount; } + // operations on/for texture generator threads + void removeOperationsForFilter(OperationFilter* filter); + bool tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter); + void scheduleOperation(QueuedOperation* operation); + private: TilesManager(); + ~TilesManager(); + int m_scheduleThread; void discardTexturesVector(unsigned long long sparedDrawCount, WTF::Vector<TileTexture*>& textures, @@ -198,7 +191,7 @@ private: unsigned int m_contentUpdates; // nr of successful tiled paints unsigned int m_webkitContentUpdates; // nr of paints from webkit - sp<TexturesGenerator> m_pixmapsGenerationThread; + sp<TexturesGenerator>* m_textureGenerators; android::Mutex m_texturesLock; diff --git a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp index f37afa4..e329191 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp @@ -32,6 +32,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "AndroidLog.h" +#include "BaseRenderer.h" #include "DrawQuadData.h" #include "GLUtils.h" #include "Tile.h" @@ -391,6 +392,7 @@ void TransferQueue::updateDirtyTiles() void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap) { + TRACE_METHOD(); if (!tryUpdateQueueWithBitmap(renderInfo, bitmap)) { // failed placing bitmap in queue, discard tile's texture so it will be // re-enqueued (and repainted) diff --git a/Source/WebCore/platform/mock/GeolocationServiceMock.cpp b/Source/WebCore/platform/mock/GeolocationServiceMock.cpp index c3ba7b4..b254cb8 100644 --- a/Source/WebCore/platform/mock/GeolocationServiceMock.cpp +++ b/Source/WebCore/platform/mock/GeolocationServiceMock.cpp @@ -80,12 +80,7 @@ void GeolocationServiceMock::setError(PassRefPtr<PositionError> error) makeGeolocationCallbackFromAllInstances(); } -#if PLATFORM(ANDROID) -// TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082 -bool GeolocationServiceMock::startUpdating(PositionOptions*, bool /* suspend */) -#else bool GeolocationServiceMock::startUpdating(PositionOptions*) -#endif { m_isActive = true; m_timer.startOneShot(0); diff --git a/Source/WebCore/platform/mock/GeolocationServiceMock.h b/Source/WebCore/platform/mock/GeolocationServiceMock.h index 1b4db93..7d02797 100755 --- a/Source/WebCore/platform/mock/GeolocationServiceMock.h +++ b/Source/WebCore/platform/mock/GeolocationServiceMock.h @@ -46,12 +46,7 @@ class GeolocationServiceMock : public GeolocationService { GeolocationServiceMock(GeolocationServiceClient*); virtual ~GeolocationServiceMock(); -#if PLATFORM(ANDROID) - // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082 - virtual bool startUpdating(PositionOptions*, bool suspend); -#else virtual bool startUpdating(PositionOptions*); -#endif virtual void stopUpdating(); static void setPosition(PassRefPtr<Geoposition> position); diff --git a/Source/WebCore/plugins/android/PluginViewAndroid.cpp b/Source/WebCore/plugins/android/PluginViewAndroid.cpp index fdf6e03..2cc95b1 100644 --- a/Source/WebCore/plugins/android/PluginViewAndroid.cpp +++ b/Source/WebCore/plugins/android/PluginViewAndroid.cpp @@ -405,7 +405,7 @@ bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPErr // our interface query is valid with no NPP instance *result = NPERR_GENERIC_ERROR; - switch (variable) { + switch ((int)variable) { case NPNVisOfflineBool: { if (value != NULL) { bool* retValue = static_cast<bool*>(value); @@ -422,7 +422,7 @@ bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPErr return true; } default: - ; // do nothing + break; // do nothing } (void)anp_getInterface(variable, value, result); @@ -490,7 +490,7 @@ void PluginView::setNPWindowIfNeeded() bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* result) { - switch (variable) { + switch ((int)variable) { case NPNVWindowNPObject: { NPObject* windowScriptObject = m_parentFrame->script()->windowScriptNPObject(); @@ -581,7 +581,7 @@ NPError PluginView::platformSetValue(NPPVariable variable, void* value) { NPError error = NPERR_GENERIC_ERROR; - switch (variable) { + switch ((int)variable) { case kRequestDrawingModel_ANPSetValue: { ANPDrawingModel model = reinterpret_cast<ANPDrawingModel>(value); if (m_window->setDrawingModel(model)) diff --git a/Source/WebKit/Android.mk b/Source/WebKit/Android.mk index c3e9798..07634b6 100644 --- a/Source/WebKit/Android.mk +++ b/Source/WebKit/Android.mk @@ -27,6 +27,9 @@ LOCAL_SRC_FILES := \ android/WebCoreSupport/EditorClientAndroid.cpp \ android/WebCoreSupport/FrameLoaderClientAndroid.cpp \ android/WebCoreSupport/FrameNetworkingContextAndroid.cpp \ + android/WebCoreSupport/GeolocationClientAndroid.cpp \ + android/WebCoreSupport/GeolocationClientImpl.cpp \ + android/WebCoreSupport/GeolocationManager.cpp \ android/WebCoreSupport/GeolocationPermissions.cpp \ android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp \ android/WebCoreSupport/MemoryUsage.cpp \ @@ -61,6 +64,7 @@ LOCAL_SRC_FILES += \ android/jni/DeviceMotionClientImpl.cpp \ android/jni/DeviceOrientationClientImpl.cpp \ android/jni/GeolocationPermissionsBridge.cpp \ + android/jni/GeolocationServiceBridge.cpp \ android/jni/JavaBridge.cpp \ android/jni/JavaSharedClient.cpp \ android/jni/MIMETypeRegistry.cpp \ diff --git a/Source/WebKit/android/AndroidLog.h b/Source/WebKit/android/AndroidLog.h index f034d35..6b6c1a0 100644 --- a/Source/WebKit/android/AndroidLog.h +++ b/Source/WebKit/android/AndroidLog.h @@ -30,6 +30,8 @@ #define LOG_TAG __FILE__ #endif +#define ATRACE_TAG ATRACE_TAG_WEBVIEW + #include <cutils/log.h> #include <utils/Trace.h> #include <wtf/CurrentTime.h> @@ -58,7 +60,7 @@ extern FILE* gRenderTreeFile; #define INT_RECT_FORMAT "[x=%d,y=%d,w=%d,h=%d]" #define INT_RECT_ARGS(ir) ir.x(), ir.y(), ir.width(), ir.height() -#define TRACE_METHOD() android::ScopedTrace __st(ATRACE_TAG_WEBVIEW, __func__); +#define TRACE_METHOD() android::ScopedTrace __st(ATRACE_TAG, __func__); #define TIME_METHOD() MethodTimer __method_timer(__func__) class MethodTimer { diff --git a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp index 907dc3c..cad23dc 100644 --- a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp +++ b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp @@ -512,39 +512,6 @@ void ChromeClientAndroid::populateVisitedLinks() android::WebViewCore::getWebViewCore(view)->populateVisitedLinks(&page->group()); } -void ChromeClientAndroid::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation) -{ - ASSERT(geolocation); - if (!m_geolocationPermissions) { - m_geolocationPermissions = new GeolocationPermissions(android::WebViewCore::getWebViewCore(frame->view()), - m_webFrame->page()->mainFrame()); - } - m_geolocationPermissions->queryPermissionState(frame); -} - -void ChromeClientAndroid::cancelGeolocationPermissionRequestForFrame(Frame* frame, WebCore::Geolocation*) -{ - if (m_geolocationPermissions) - m_geolocationPermissions->cancelPermissionStateQuery(frame); -} - -void ChromeClientAndroid::provideGeolocationPermissions(const String &origin, bool allow, bool remember) -{ - ASSERT(m_geolocationPermissions); - m_geolocationPermissions->providePermissionState(origin, allow, remember); -} - -void ChromeClientAndroid::storeGeolocationPermissions() -{ - GeolocationPermissions::maybeStorePermanentPermissions(); -} - -void ChromeClientAndroid::onMainFrameLoadStarted() -{ - if (m_geolocationPermissions.get()) - m_geolocationPermissions->resetTemporaryPermissionStates(); -} - void ChromeClientAndroid::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> chooser) { diff --git a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.h b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.h index 36576e6..82f3a23 100644 --- a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.h +++ b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.h @@ -28,7 +28,6 @@ #include "ChromeClient.h" -#include "GeolocationPermissions.h" #include "PopupMenu.h" #include "SearchPopupMenu.h" #include "Timer.h" @@ -47,13 +46,13 @@ namespace android { class ChromeClientAndroid : public ChromeClient { public: - ChromeClientAndroid() : m_webFrame(0), m_geolocationPermissions(0) + ChromeClientAndroid() : m_webFrame(0) #if USE(ACCELERATED_COMPOSITING) - , m_rootGraphicsLayer(0) - , m_needsLayerSync(false) + , m_rootGraphicsLayer(0) + , m_needsLayerSync(false) #endif - , m_triedToReclaimDBQuota(false) - { } + , m_triedToReclaimDBQuota(false) + { } virtual void chromeDestroyed(); virtual void setWindowRect(const FloatRect&); @@ -147,12 +146,9 @@ namespace android { #endif // Methods used to request and provide Geolocation permissions. - virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*); - virtual void cancelGeolocationPermissionRequestForFrame(WebCore::Frame*, WebCore::Geolocation*); - // Android-specific - void provideGeolocationPermissions(const String &origin, bool allow, bool remember); - void storeGeolocationPermissions(); - void onMainFrameLoadStarted(); + // Not used with client-based Geolocation + virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*) { ASSERT_NOT_REACHED(); } + virtual void cancelGeolocationPermissionRequestForFrame(WebCore::Frame*, WebCore::Geolocation*) { ASSERT_NOT_REACHED(); } virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>); virtual void setCursor(const Cursor&); @@ -202,8 +198,6 @@ namespace android { private: android::WebFrame* m_webFrame; - // The Geolocation permissions manager. - OwnPtr<GeolocationPermissions> m_geolocationPermissions; #if USE(ACCELERATED_COMPOSITING) WebCore::GraphicsLayer* m_rootGraphicsLayer; bool m_needsLayerSync; diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.cpp new file mode 100644 index 0000000..7c5b207 --- /dev/null +++ b/Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "GeolocationClientAndroid.h" + +#include "WebViewCore.h" + +#include <Frame.h> +#include <Page.h> + +using WebCore::Geolocation; +using WebCore::GeolocationClient; +using WebCore::GeolocationController; +using WebCore::GeolocationPosition; + +namespace android { + +GeolocationClientAndroid::GeolocationClientAndroid() : m_webViewCore(0) +{ +} + +GeolocationClientAndroid::~GeolocationClientAndroid() +{ +} + +void GeolocationClientAndroid::geolocationDestroyed() +{ + delete this; +} + +void GeolocationClientAndroid::startUpdating() +{ + client()->startUpdating(); +} + +void GeolocationClientAndroid::stopUpdating() +{ + client()->stopUpdating(); +} + +void GeolocationClientAndroid::setEnableHighAccuracy(bool enableHighAccuracy) +{ + client()->setEnableHighAccuracy(enableHighAccuracy); +} + +GeolocationPosition* GeolocationClientAndroid::lastPosition() +{ + return client()->lastPosition(); +} + +void GeolocationClientAndroid::requestPermission(Geolocation* geolocation) +{ + client()->requestPermission(geolocation); +} + +void GeolocationClientAndroid::cancelPermissionRequest(Geolocation* geolocation) +{ + client()->cancelPermissionRequest(geolocation); +} + +void GeolocationClientAndroid::setWebViewCore(WebViewCore* webViewCore) +{ + ASSERT(!m_webViewCore); + m_webViewCore = webViewCore; + ASSERT(m_webViewCore); +} + +GeolocationClient* GeolocationClientAndroid::client() const +{ + return m_webViewCore->geolocationManager()->client(); +} + +} // namespace android diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.h b/Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.h new file mode 100644 index 0000000..22405e1 --- /dev/null +++ b/Source/WebKit/android/WebCoreSupport/GeolocationClientAndroid.h @@ -0,0 +1,61 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GeolocationClientAndroid_h +#define GeolocationClientAndroid_h + +#include <GeolocationClient.h> + +namespace android { + +class WebViewCore; + +// The Android implementation of GeolocationClient. Acts as a proxy to +// the real or mock impl, which is owned by the GeolocationManager. +class GeolocationClientAndroid : public WebCore::GeolocationClient { +public: + GeolocationClientAndroid(); + virtual ~GeolocationClientAndroid(); + + // GeolocationClient + virtual void geolocationDestroyed(); + virtual void startUpdating(); + virtual void stopUpdating(); + virtual void setEnableHighAccuracy(bool); + virtual WebCore::GeolocationPosition* lastPosition(); + virtual void requestPermission(WebCore::Geolocation*); + virtual void cancelPermissionRequest(WebCore::Geolocation*); + + void setWebViewCore(WebViewCore*); + +private: + WebCore::GeolocationClient* client() const; + + WebViewCore* m_webViewCore; +}; + +} // namespace android + +#endif // GeolocationClientAndroid_h diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.cpp b/Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.cpp new file mode 100644 index 0000000..6291b7d --- /dev/null +++ b/Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.cpp @@ -0,0 +1,223 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "GeolocationClientImpl.h" + +#include <Frame.h> +#include <Page.h> +#include <GeolocationController.h> +#include <GeolocationError.h> +#include <GeolocationPosition.h> +#include <WebViewCore.h> +#if PLATFORM(ANDROID) +// Required for sim-eng build +#include <math.h> +#endif +#include <wtf/CurrentTime.h> + +using WebCore::Geolocation; +using WebCore::GeolocationError; +using WebCore::GeolocationPosition; +using WebCore::Timer; + +using namespace std; + +namespace { + +bool isPositionMovement(GeolocationPosition* position1, GeolocationPosition* position2) +{ + // For the small distances in which we are likely concerned, it's reasonable + // to approximate the distance between the two positions as the sum of the + // differences in latitude and longitude. + double delta = fabs(position1->latitude() - position2->latitude()) + fabs(position1->longitude() - position2->longitude()); + // Approximate conversion from degrees of arc to metres. + delta *= 60 * 1852; + // The threshold is when the distance between the two positions exceeds the + // worse (larger) of the two accuracies. + int maxAccuracy = max(position1->accuracy(), position2->accuracy()); + return delta > maxAccuracy; +} + +bool isPositionMoreAccurate(GeolocationPosition* position1, GeolocationPosition* position2) +{ + return position2->accuracy() < position1->accuracy(); +} + +bool isPositionMoreTimely(GeolocationPosition* position1) +{ + double currentTime = WTF::currentTime(); + double maximumAge = 10 * 60; // 10 minutes + return currentTime - position1->timestamp() > maximumAge; +} + +} // anonymous namespace + +namespace android { + +GeolocationClientImpl::GeolocationClientImpl(WebViewCore* webViewCore) + : m_webViewCore(webViewCore) + , m_timer(this, &GeolocationClientImpl::timerFired) + , m_isSuspended(false) + , m_useGps(false) +{ +} + +GeolocationClientImpl::~GeolocationClientImpl() +{ +} + +void GeolocationClientImpl::geolocationDestroyed() +{ + // Lifetime is managed by GeolocationManager. +} + +void GeolocationClientImpl::startUpdating() +{ + // This method is called every time a new watch or one-shot position request + // is started. If we already have a position or an error, call back + // immediately. + if (m_lastPosition || m_lastError) { + m_timer.startOneShot(0); + } + + // Lazilly create the Java object. + bool haveJavaBridge = m_javaBridge; + if (!haveJavaBridge) + m_javaBridge.set(new GeolocationServiceBridge(this, m_webViewCore)); + ASSERT(m_javaBridge); + + // Set whether to use GPS before we start the implementation. + m_javaBridge->setEnableGps(m_useGps); + + // If we're suspended, don't start the service. It will be started when we + // get the call to resume(). + if (!haveJavaBridge && !m_isSuspended) + m_javaBridge->start(); +} + +void GeolocationClientImpl::stopUpdating() +{ + // TODO: It would be good to re-use the Java bridge object. + m_javaBridge.clear(); + m_useGps = false; + // Reset last position and error to make sure that we always try to get a + // new position from the client when a request is first made. + m_lastPosition = 0; + m_lastError = 0; + + if (m_timer.isActive()) + m_timer.stop(); +} + +void GeolocationClientImpl::setEnableHighAccuracy(bool enableHighAccuracy) +{ + // On Android, high power == GPS. + m_useGps = enableHighAccuracy; + if (m_javaBridge) + m_javaBridge->setEnableGps(m_useGps); +} + +GeolocationPosition* GeolocationClientImpl::lastPosition() +{ + return m_lastPosition.get(); +} + +void GeolocationClientImpl::requestPermission(Geolocation* geolocation) +{ + permissions()->queryPermissionState(geolocation->frame()); +} + +void GeolocationClientImpl::cancelPermissionRequest(Geolocation* geolocation) +{ + permissions()->cancelPermissionStateQuery(geolocation->frame()); +} + +// Note that there is no guarantee that subsequent calls to this method offer a +// more accurate or updated position. +void GeolocationClientImpl::newPositionAvailable(PassRefPtr<GeolocationPosition> position) +{ + ASSERT(position); + if (!m_lastPosition + || isPositionMovement(m_lastPosition.get(), position.get()) + || isPositionMoreAccurate(m_lastPosition.get(), position.get()) + || isPositionMoreTimely(m_lastPosition.get())) { + m_lastPosition = position; + // Remove the last error. + m_lastError = 0; + m_webViewCore->mainFrame()->page()->geolocationController()->positionChanged(m_lastPosition.get()); + } +} + +void GeolocationClientImpl::newErrorAvailable(PassRefPtr<WebCore::GeolocationError> error) +{ + ASSERT(error); + // We leave the last position + m_lastError = error; + m_webViewCore->mainFrame()->page()->geolocationController()->errorOccurred(m_lastError.get()); +} + +void GeolocationClientImpl::suspend() +{ + m_isSuspended = true; + if (m_javaBridge) + m_javaBridge->stop(); +} + +void GeolocationClientImpl::resume() +{ + m_isSuspended = false; + if (m_javaBridge) + m_javaBridge->start(); +} + +void GeolocationClientImpl::resetTemporaryPermissionStates() +{ + permissions()->resetTemporaryPermissionStates(); +} + +void GeolocationClientImpl::providePermissionState(String origin, bool allow, bool remember) +{ + permissions()->providePermissionState(origin, allow, remember); +} + +GeolocationPermissions* GeolocationClientImpl::permissions() const +{ + if (!m_permissions) + m_permissions = new GeolocationPermissions(m_webViewCore); + return m_permissions.get(); +} + +void GeolocationClientImpl::timerFired(Timer<GeolocationClientImpl>* timer) +{ + ASSERT(&m_timer == timer); + ASSERT(m_lastPosition || m_lastError); + if (m_lastPosition) + m_webViewCore->mainFrame()->page()->geolocationController()->positionChanged(m_lastPosition.get()); + else + m_webViewCore->mainFrame()->page()->geolocationController()->errorOccurred(m_lastError.get()); +} + +} // namespace android diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.h b/Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.h new file mode 100644 index 0000000..26e6c0c --- /dev/null +++ b/Source/WebKit/android/WebCoreSupport/GeolocationClientImpl.h @@ -0,0 +1,86 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GeolocationClientImpl_h +#define GeolocationClientImpl_h + +#include "GeolocationServiceBridge.h" +#include "GeolocationClient.h" +#include "GeolocationPermissions.h" + +#include <Timer.h> +#include <wtf/OwnPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { +class Geolocation; +class GeolocationController; +} + +namespace android { + +class WebViewCore; + +// The real implementation of GeolocationClient. +class GeolocationClientImpl : public WebCore::GeolocationClient, public GeolocationServiceBridge::Listener { +public: + GeolocationClientImpl(WebViewCore*); + virtual ~GeolocationClientImpl(); + + // WebCore::GeolocationClient + virtual void geolocationDestroyed(); + virtual void startUpdating(); + virtual void stopUpdating(); + virtual void setEnableHighAccuracy(bool); + virtual WebCore::GeolocationPosition* lastPosition(); + virtual void requestPermission(WebCore::Geolocation*); + virtual void cancelPermissionRequest(WebCore::Geolocation*); + + // GeolocationServiceBridge::Listener + virtual void newPositionAvailable(PassRefPtr<WebCore::GeolocationPosition>); + virtual void newErrorAvailable(PassRefPtr<WebCore::GeolocationError>); + + void suspend(); + void resume(); + void resetTemporaryPermissionStates(); + void providePermissionState(String origin, bool allow, bool remember); + +private: + GeolocationPermissions* permissions() const; + void timerFired(WebCore::Timer<GeolocationClientImpl>*); + + WebViewCore* m_webViewCore; + RefPtr<WebCore::GeolocationPosition> m_lastPosition; + RefPtr<WebCore::GeolocationError> m_lastError; + OwnPtr<GeolocationServiceBridge> m_javaBridge; + mutable OwnPtr<GeolocationPermissions> m_permissions; + WebCore::Timer<GeolocationClientImpl> m_timer; + bool m_isSuspended; + bool m_useGps; +}; + +} // namespace android + +#endif // GeolocationClientImpl_h diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationManager.cpp b/Source/WebKit/android/WebCoreSupport/GeolocationManager.cpp new file mode 100644 index 0000000..cbf399d --- /dev/null +++ b/Source/WebKit/android/WebCoreSupport/GeolocationManager.cpp @@ -0,0 +1,125 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "GeolocationManager.h" + +#include "GeolocationClientImpl.h" +#include "WebViewCore.h" + +#include <Frame.h> +#include <GeolocationError.h> +#include <GeolocationPosition.h> +#include <JNIHelp.h> +#include <Page.h> + +using WebCore::GeolocationClient; +using WebCore::GeolocationClientMock; + +namespace android { + +GeolocationManager::GeolocationManager(WebViewCore* webViewCore) + : m_useMock(false) + , m_webViewCore(webViewCore) +{ +} + +GeolocationClient* GeolocationManager::client() const +{ + if (m_useMock) + return mockClient(); + return realClient(); +} + +void GeolocationManager::suspendRealClient() +{ + // Don't create the real client if it's not present. + if (m_realClient) + m_realClient->suspend(); +} + +void GeolocationManager::resumeRealClient() +{ + // Don't create the real client if it's not present. + if (m_realClient) + m_realClient->resume(); +} + +void GeolocationManager::resetRealClientTemporaryPermissionStates() +{ + // Don't create the real client if it's not present. + if (m_realClient) + m_realClient->resetTemporaryPermissionStates(); +} + +void GeolocationManager::provideRealClientPermissionState(WTF::String origin, bool allow, bool remember) +{ + // Don't create the real client if it's not present. + if (m_realClient) + m_realClient->providePermissionState(origin, allow, remember); +} + +void GeolocationManager::setUseMock() +{ + m_useMock = true; + m_mockClient.clear(); +} + +void GeolocationManager::setMockPosition(PassRefPtr<WebCore::GeolocationPosition> position) +{ + ASSERT(m_useMock); + mockClient()->setPosition(position); +} + +void GeolocationManager::setMockError(PassRefPtr<WebCore::GeolocationError> error) +{ + ASSERT(m_useMock); + mockClient()->setError(error); +} + +void GeolocationManager::setMockPermission(bool allowed) +{ + ASSERT(m_useMock); + mockClient()->setPermission(allowed); +} + +GeolocationClientImpl* GeolocationManager::realClient() const +{ + if (!m_realClient) + m_realClient.set(new GeolocationClientImpl(m_webViewCore)); + return m_realClient.get(); +} + +GeolocationClientMock* GeolocationManager::mockClient() const +{ + ASSERT(m_useMock); + if (!m_mockClient) { + m_mockClient.set(new GeolocationClientMock); + m_mockClient->setController(m_webViewCore->mainFrame()->page()->geolocationController()); + } + return m_mockClient.get(); +} + +} // namespace android diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationManager.h b/Source/WebKit/android/WebCoreSupport/GeolocationManager.h new file mode 100644 index 0000000..6459db1 --- /dev/null +++ b/Source/WebKit/android/WebCoreSupport/GeolocationManager.h @@ -0,0 +1,80 @@ +/* + * Copyright 2012, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GeolocationManager_h +#define GeolocationManager_h + +#include "GeolocationClientImpl.h" + +#include <GeolocationClientMock.h> +#include <OwnPtr.h> +#include <PassRefPtr.h> + +namespace WebCore { +class GeolocationError; +class GeolocationPosition; +} + +namespace android { + +class GeolocationClientImpl; +class WebViewCore; + +// This class takes care of the fact that the client used for Geolocation +// may be either the real implementation or a mock. It also handles setting the +// data on the mock client. This class is owned by WebViewCore and exists to +// keep cruft out of that class. +class GeolocationManager { +public: + GeolocationManager(WebViewCore*); + + // For use by GeolocationClientAndroid. Gets the current client, either the + // real or mock. + WebCore::GeolocationClient* client() const; + + void suspendRealClient(); + void resumeRealClient(); + void resetRealClientTemporaryPermissionStates(); + void provideRealClientPermissionState(WTF::String origin, bool allow, bool remember); + + // Sets use of the Geolocation mock client. Also resets that client. + void setUseMock(); + void setMockPosition(PassRefPtr<WebCore::GeolocationPosition>); + void setMockError(PassRefPtr<WebCore::GeolocationError>); + void setMockPermission(bool allowed); + +private: + GeolocationClientImpl* realClient() const; + WebCore::GeolocationClientMock* mockClient() const; + + bool m_useMock; + WebViewCore* m_webViewCore; + mutable OwnPtr<GeolocationClientImpl> m_realClient; + mutable OwnPtr<WebCore::GeolocationClientMock> m_mockClient; +}; + +} // namespace android + +#endif // GeolocationManager_h diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp b/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp index 36a9b61..fb29bd6 100755 --- a/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp +++ b/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp @@ -26,16 +26,16 @@ #include "config.h" #include "GeolocationPermissions.h" -#include "DOMWindow.h" -#include "Frame.h" -#include "Geolocation.h" -#include "Navigator.h" -#include "SQLiteDatabase.h" -#include "SQLiteFileSystem.h" -#include "SQLiteStatement.h" -#include "SQLiteTransaction.h" #include "WebViewCore.h" +#include <DOMWindow.h> +#include <Frame.h> +#include <Geolocation.h> +#include <Navigator.h> +#include <SQLiteDatabase.h> +#include <SQLiteFileSystem.h> +#include <SQLiteStatement.h> +#include <SQLiteTransaction.h> #include <text/CString.h> using namespace WebCore; @@ -51,9 +51,8 @@ String GeolocationPermissions::s_databasePath; static const char* databaseName = "GeolocationPermissions.db"; -GeolocationPermissions::GeolocationPermissions(WebViewCore* webViewCore, Frame* mainFrame) +GeolocationPermissions::GeolocationPermissions(WebViewCore* webViewCore) : m_webViewCore(webViewCore) - , m_mainFrame(mainFrame) , m_timer(this, &GeolocationPermissions::timerFired) { @@ -266,7 +265,7 @@ void GeolocationPermissions::maybeCallbackFrames(String origin, bool allow) // or have their contents replaced. Even uniqueChildName is not unique when // frames are dynamically deleted and created. Instead, we simply call back // to the Geolocation object in all frames from the correct origin. - for (Frame* frame = m_mainFrame; frame; frame = frame->tree()->traverseNext()) { + for (Frame* frame = m_webViewCore->mainFrame(); frame; frame = frame->tree()->traverseNext()) { if (origin == frame->document()->securityOrigin()->toString()) { // If the page has changed, it may no longer have a Geolocation // object. diff --git a/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.h b/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.h index fb31dfe..8f4b96e 100644 --- a/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.h +++ b/Source/WebKit/android/WebCoreSupport/GeolocationPermissions.h @@ -26,9 +26,8 @@ #ifndef GeolocationPermissions_h #define GeolocationPermissions_h -#include "PlatformString.h" -#include "Timer.h" - +#include <PlatformString.h> +#include <Timer.h> #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/RefCounted.h> @@ -63,9 +62,8 @@ namespace android { class GeolocationPermissions : public RefCounted<GeolocationPermissions> { public: // Creates the GeolocationPermissions object to manage permissions for - // the specified main frame (i.e. tab). The WebViewCore is used to - // communicate with the browser to display UI. - GeolocationPermissions(WebViewCore* webViewCore, WebCore::Frame* mainFrame); + // the WebView. + GeolocationPermissions(WebViewCore* webViewCore); virtual ~GeolocationPermissions(); // Queries the permission state for the specified frame. If the @@ -140,7 +138,6 @@ namespace android { const WTF::String& nextOriginInQueue(); WebViewCore* m_webViewCore; - WebCore::Frame* m_mainFrame; // A vector of the origins queued to make a permission request. // The first in the vector is the origin currently making the request. typedef Vector<WTF::String> OriginVector; diff --git a/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp b/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp index 9b8aac8..56e7e24 100644 --- a/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp +++ b/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp @@ -111,12 +111,6 @@ NPObject* PlatformBridge::pluginScriptableObject(Widget* widget) return pluginView->getNPObject(); } -bool PlatformBridge::isWebViewPaused(const WebCore::FrameView* frameView) -{ - android::WebViewCore* webViewCore = android::WebViewCore::getWebViewCore(frameView); - return webViewCore->isPaused(); -} - bool PlatformBridge::popupsAllowed(NPP) { return false; diff --git a/Source/WebCore/platform/android/GeolocationServiceBridge.cpp b/Source/WebKit/android/jni/GeolocationServiceBridge.cpp index 697b63b..056c788 100644 --- a/Source/WebCore/platform/android/GeolocationServiceBridge.cpp +++ b/Source/WebKit/android/jni/GeolocationServiceBridge.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2009, The Android Open Source Project + * Copyright 2012, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,16 +26,17 @@ #include "config.h" #include "GeolocationServiceBridge.h" -#include "Frame.h" -#include "GeolocationServiceAndroid.h" -#include "Geoposition.h" -#include "PositionError.h" #include "WebViewCore.h" -#include <JNIHelp.h> -namespace WebCore { +#include <GeolocationError.h> +#include <GeolocationPosition.h> +#include <JNIHelp.h> using JSC::Bindings::getJNIEnv; +using WebCore::GeolocationError; +using WebCore::GeolocationPosition; + +namespace android { static const char* javaGeolocationServiceClassName = "android/webkit/GeolocationService"; enum javaGeolocationServiceClassMethods { @@ -71,12 +72,12 @@ enum javaLocationClassMethods { }; static jmethodID javaLocationClassMethodIDs[LocationMethodCount]; -GeolocationServiceBridge::GeolocationServiceBridge(ListenerInterface* listener, Frame* frame) +GeolocationServiceBridge::GeolocationServiceBridge(Listener* listener, WebViewCore* webViewCore) : m_listener(listener) , m_javaGeolocationServiceObject(0) { ASSERT(m_listener); - startJavaImplementation(frame); + startJavaImplementation(webViewCore); } GeolocationServiceBridge::~GeolocationServiceBridge() @@ -115,18 +116,17 @@ void GeolocationServiceBridge::newLocationAvailable(JNIEnv* env, jclass, jlong n ASSERT(nativeObject); ASSERT(location); GeolocationServiceBridge* object = reinterpret_cast<GeolocationServiceBridge*>(nativeObject); - object->m_listener->newPositionAvailable(toGeoposition(env, location)); + object->m_listener->newPositionAvailable(toGeolocationPosition(env, location)); } void GeolocationServiceBridge::newErrorAvailable(JNIEnv* env, jclass, jlong nativeObject, jstring message) { GeolocationServiceBridge* object = reinterpret_cast<GeolocationServiceBridge*>(nativeObject); - RefPtr<PositionError> error = - PositionError::create(PositionError::POSITION_UNAVAILABLE, android::jstringToWtfString(env, message)); + RefPtr<GeolocationError> error = GeolocationError::create(GeolocationError::PositionUnavailable, jstringToWtfString(env, message)); object->m_listener->newErrorAvailable(error.release()); } -PassRefPtr<Geoposition> GeolocationServiceBridge::toGeoposition(JNIEnv *env, const jobject &location) +PassRefPtr<GeolocationPosition> GeolocationServiceBridge::toGeolocationPosition(JNIEnv *env, const jobject &location) { // Altitude is optional and may not be supplied. bool hasAltitude = @@ -155,21 +155,18 @@ PassRefPtr<Geoposition> GeolocationServiceBridge::toGeoposition(JNIEnv *env, con env->CallFloatMethod(location, javaLocationClassMethodIDs[LocationMethodGetSpeed]) : 0.0; - RefPtr<Coordinates> newCoordinates = WebCore::Coordinates::create( + return GeolocationPosition::create( + env->CallLongMethod(location, javaLocationClassMethodIDs[LocationMethodGetTime]) / 1000.0, env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetLatitude]), env->CallDoubleMethod(location, javaLocationClassMethodIDs[LocationMethodGetLongitude]), - hasAltitude, Altitude, Accuracy, + hasAltitude, Altitude, false, 0.0, // AltitudeAccuracy not provided. hasHeading, heading, hasSpeed, speed); - - return WebCore::Geoposition::create( - newCoordinates.release(), - env->CallLongMethod(location, javaLocationClassMethodIDs[LocationMethodGetTime])); } -void GeolocationServiceBridge::startJavaImplementation(Frame* frame) +void GeolocationServiceBridge::startJavaImplementation(WebViewCore* webViewCore) { JNIEnv* env = getJNIEnv(); @@ -188,7 +185,7 @@ void GeolocationServiceBridge::startJavaImplementation(Frame* frame) env->GetMethodID(javaGeolocationServiceClass, "setEnableGps", "(Z)V"); // Create the Java GeolocationService object. - jobject context = android::WebViewCore::getWebViewCore(frame->view())->getContext(); + jobject context = webViewCore->getContext(); if (!context) return; jlong nativeObject = reinterpret_cast<jlong>(this); @@ -237,10 +234,9 @@ void GeolocationServiceBridge::startJavaImplementation(Frame* frame) void GeolocationServiceBridge::stopJavaImplementation() { - // Called by GeolocationServiceAndroid on WebKit thread. if (!m_javaGeolocationServiceObject) return; getJNIEnv()->DeleteGlobalRef(m_javaGeolocationServiceObject); } -} // namespace WebCore +} // namespace android diff --git a/Source/WebCore/platform/android/GeolocationServiceBridge.h b/Source/WebKit/android/jni/GeolocationServiceBridge.h index 3997d65..826ba71 100644 --- a/Source/WebCore/platform/android/GeolocationServiceBridge.h +++ b/Source/WebKit/android/jni/GeolocationServiceBridge.h @@ -1,5 +1,5 @@ /* - * Copyright 2009, The Android Open Source Project + * Copyright 2012, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,22 +26,31 @@ #ifndef GeolocationServiceBridge_h #define GeolocationServiceBridge_h -#include "JNIUtility.h" +#include <JNIUtility.h> #include <wtf/PassRefPtr.h> namespace WebCore { +class GeolocationError; +class GeolocationPosition; +} -class Frame; -class GeolocationServiceAndroid; -class Geoposition; +namespace android { + +class WebViewCore; // GeolocationServiceBridge is the bridge to the Java implementation. It manages // the lifetime of the Java object. It is an implementation detail of -// GeolocationServiceAndroid. +// GeolocationClientAndroid. class GeolocationServiceBridge { public: - typedef GeolocationServiceAndroid ListenerInterface; - GeolocationServiceBridge(ListenerInterface* listener, Frame* frame); + class Listener { + public: + virtual ~Listener() {} + virtual void newPositionAvailable(PassRefPtr<WebCore::GeolocationPosition>) = 0; + virtual void newErrorAvailable(PassRefPtr<WebCore::GeolocationError>) = 0; + }; + + GeolocationServiceBridge(Listener*, WebViewCore*); ~GeolocationServiceBridge(); bool start(); @@ -51,16 +60,16 @@ public: // Static wrapper functions to hide JNI nastiness. static void newLocationAvailable(JNIEnv *env, jclass, jlong nativeObject, jobject location); static void newErrorAvailable(JNIEnv *env, jclass, jlong nativeObject, jstring message); - static PassRefPtr<Geoposition> toGeoposition(JNIEnv *env, const jobject &location); + static PassRefPtr<WebCore::GeolocationPosition> toGeolocationPosition(JNIEnv *env, const jobject &location); private: - void startJavaImplementation(Frame* frame); + void startJavaImplementation(WebViewCore*); void stopJavaImplementation(); - ListenerInterface* m_listener; + Listener* m_listener; jobject m_javaGeolocationServiceObject; }; -} // namespace WebCore +} // namespace android #endif // GeolocationServiceBridge_h diff --git a/Source/WebKit/android/jni/MockGeolocation.cpp b/Source/WebKit/android/jni/MockGeolocation.cpp index 250953f..164c37d 100755 --- a/Source/WebKit/android/jni/MockGeolocation.cpp +++ b/Source/WebKit/android/jni/MockGeolocation.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2009, The Android Open Source Project + * Copyright 2012, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,19 +23,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// The functions in this file are used to configure the mock GeolocationService +// The functions in this file are used to configure the mock Geolocation client // for the LayoutTests. #include "config.h" -#include "Coordinates.h" -#include "GeolocationServiceMock.h" -#include "Geoposition.h" -#include "JavaSharedClient.h" -#include "PositionError.h" -#include "WebCoreJni.h" -#include <JNIHelp.h> -#include <JNIUtility.h> +#include "WebViewCore.h" + +#include <GeolocationError.h> +#include <GeolocationPosition.h> +#include "ScopedLocalRef.h" #include <wtf/CurrentTime.h> using namespace WebCore; @@ -44,30 +41,46 @@ namespace android { static const char* javaMockGeolocationClass = "android/webkit/MockGeolocation"; -static void setPosition(JNIEnv* env, jobject, double latitude, double longitude, double accuracy) +WebViewCore* getWebViewCore(JNIEnv* env, jobject webViewCore) +{ + ScopedLocalRef<jclass> webViewCoreClass(env, env->FindClass("android/webkit/WebViewCore")); + jfieldID nativeClassField = env->GetFieldID(webViewCoreClass.get(), "mNativeClass", "I"); + return reinterpret_cast<WebViewCore*>(env->GetIntField(webViewCore, nativeClassField)); +} + +static void setUseMock(JNIEnv* env, jobject, jobject webViewCore) +{ + getWebViewCore(env, webViewCore)->geolocationManager()->setUseMock(); +} + +static void setPosition(JNIEnv* env, jobject, jobject webViewCore, double latitude, double longitude, double accuracy) +{ + getWebViewCore(env, webViewCore)->geolocationManager()->setMockPosition(GeolocationPosition::create(WTF::currentTime(), + latitude, + longitude, + accuracy, + false, 0.0, // altitude, + false, 0.0, // altitudeAccuracy, + false, 0.0, // heading + false, 0.0)); // speed +} + +static void setError(JNIEnv* env, jobject, jobject webViewCore, int code, jstring message) { - RefPtr<Coordinates> coordinates = Coordinates::create(latitude, - longitude, - false, 0.0, // altitude, - accuracy, - false, 0.0, // altitudeAccuracy, - false, 0.0, // heading - false, 0.0); // speed - RefPtr<Geoposition> position = Geoposition::create(coordinates.release(), WTF::currentTimeMS()); - GeolocationServiceMock::setPosition(position.release()); + GeolocationError::ErrorCode codeEnum = static_cast<GeolocationError::ErrorCode>(code); + getWebViewCore(env, webViewCore)->geolocationManager()->setMockError(GeolocationError::create(codeEnum, jstringToWtfString(env, message))); } -static void setError(JNIEnv* env, jobject, int code, jstring message) +static void setPermission(JNIEnv* env, jobject, jobject webViewCore, bool allow) { - PositionError::ErrorCode codeEnum = static_cast<PositionError::ErrorCode>(code); - String messageString = jstringToWtfString(env, message); - RefPtr<PositionError> error = PositionError::create(codeEnum, messageString); - GeolocationServiceMock::setError(error.release()); + getWebViewCore(env, webViewCore)->geolocationManager()->setMockPermission(allow); } static JNINativeMethod gMockGeolocationMethods[] = { - { "nativeSetPosition", "(DDD)V", (void*) setPosition }, - { "nativeSetError", "(ILjava/lang/String;)V", (void*) setError } + { "nativeSetUseMock", "(Landroid/webkit/WebViewCore;)V", (void*) setUseMock }, + { "nativeSetPosition", "(Landroid/webkit/WebViewCore;DDD)V", (void*) setPosition }, + { "nativeSetError", "(Landroid/webkit/WebViewCore;ILjava/lang/String;)V", (void*) setError }, + { "nativeSetPermission", "(Landroid/webkit/WebViewCore;Z)V", (void*) setPermission }, }; int registerMockGeolocation(JNIEnv* env) diff --git a/Source/WebKit/android/jni/PicturePile.cpp b/Source/WebKit/android/jni/PicturePile.cpp index ccdfa59..6a36ccf 100644 --- a/Source/WebKit/android/jni/PicturePile.cpp +++ b/Source/WebKit/android/jni/PicturePile.cpp @@ -35,11 +35,17 @@ #include "PlatformGraphicsContextSkia.h" #include "SkCanvas.h" #include "SkNWayCanvas.h" -#include "SkPicture.h" #include "SkPixelRef.h" #include "SkRect.h" #include "SkRegion.h" +#if USE_RECORDING_CONTEXT +#include "GraphicsOperationCollection.h" +#include "PlatformGraphicsContextRecording.h" +#else +#include "SkPicture.h" +#endif + #define ENABLE_PRERENDERED_INVALS true #define MAX_OVERLAP_COUNT 2 #define MAX_OVERLAP_AREA .7 @@ -57,6 +63,20 @@ static IntRect extractClipBounds(SkCanvas* canvas, const IntSize& size) { return enclosingIntRect(clip); } +PictureContainer::PictureContainer(const PictureContainer& other) + : picture(other.picture) + , area(other.area) + , dirty(other.dirty) + , prerendered(other.prerendered) +{ + SkSafeRef(picture); +} + +PictureContainer::~PictureContainer() +{ + SkSafeUnref(picture); +} + PicturePile::PicturePile(const PicturePile& other) : m_size(other.m_size) , m_pile(other.m_pile) @@ -64,15 +84,6 @@ PicturePile::PicturePile(const PicturePile& other) { } -PicturePile::PicturePile(SkPicture* picture) -{ - m_size = IntSize(picture->width(), picture->height()); - PictureContainer pc(IntRect(0, 0, m_size.width(), m_size.height())); - pc.picture = picture; - pc.dirty = false; - m_pile.append(pc); -} - void PicturePile::draw(SkCanvas* canvas) { /* Loop down recursively, subtracting the previous clip from the SkRegion, @@ -81,7 +92,6 @@ void PicturePile::draw(SkCanvas* canvas) * the rect bounds of the SkRegion for the clip, so this still can't be * used for translucent surfaces */ - TRACE_METHOD(); IntRect clipBounds = extractClipBounds(canvas, m_size); SkRegion clipRegion(toSkIRect(clipBounds)); drawWithClipRecursive(canvas, clipRegion, m_pile.size() - 1); @@ -107,8 +117,7 @@ void PicturePile::drawWithClipRecursive(SkCanvas* canvas, SkRegion& clipRegion, drawWithClipRecursive(canvas, clipRegion, index - 1); int saved = canvas->save(); canvas->clipRect(intersection); - canvas->translate(pc.area.x(), pc.area.y()); - canvas->drawPicture(*pc.picture); + drawPicture(canvas, pc); canvas->restoreToCount(saved); } else drawWithClipRecursive(canvas, clipRegion, index - 1); @@ -163,43 +172,8 @@ void PicturePile::updatePicturesIfNeeded(PicturePainter* painter) void PicturePile::updatePicture(PicturePainter* painter, PictureContainer& pc) { - /* The ref counting here is a bit unusual. What happens is begin/end recording - * will ref/unref the recording canvas. However, 'canvas' might be pointing - * at an SkNWayCanvas instead of the recording canvas, which needs to be - * unref'd. Thus what we do is ref the recording canvas so that we can - * always unref whatever canvas we have at the end. - */ TRACE_METHOD(); - SkPicture* picture = new SkPicture(); - SkCanvas* canvas = picture->beginRecording(pc.area.width(), pc.area.height(), - SkPicture::kUsePathBoundsForClip_RecordingFlag); - SkSafeRef(canvas); - canvas->translate(-pc.area.x(), -pc.area.y()); - IntRect drawArea = pc.area; - if (pc.prerendered.get()) { - SkCanvas* prerender = painter->createPrerenderCanvas(pc.prerendered.get()); - if (!prerender) { - ALOGV("Failed to create prerendered for " INT_RECT_FORMAT, - INT_RECT_ARGS(pc.prerendered->area)); - pc.prerendered.clear(); - } else { - drawArea.unite(pc.prerendered->area); - SkNWayCanvas* nwayCanvas = new SkNWayCanvas(drawArea.width(), drawArea.height()); - nwayCanvas->translate(-drawArea.x(), -drawArea.y()); - nwayCanvas->addCanvas(canvas); - nwayCanvas->addCanvas(prerender); - SkSafeUnref(canvas); - SkSafeUnref(prerender); - canvas = nwayCanvas; - } - } - WebCore::PlatformGraphicsContextSkia pgc(canvas); - WebCore::GraphicsContext gc(&pgc); - ALOGV("painting picture: " INT_RECT_FORMAT, INT_RECT_ARGS(drawArea)); - painter->paintContents(&gc, drawArea); - SkSafeUnref(canvas); - picture->endRecording(); - + Picture* picture = recordPicture(painter, pc); SkSafeUnref(pc.picture); pc.picture = picture; pc.dirty = false; @@ -298,4 +272,69 @@ PrerenderedInval* PicturePile::prerenderedInvalForArea(const IntRect& area) return 0; } +#if USE_RECORDING_CONTEXT +void PicturePile::drawPicture(SkCanvas* canvas, PictureContainer& pc) +{ + PlatformGraphicsContextSkia pgc(canvas); + pc.picture->apply(&pgc); +} + +Picture* PicturePile::recordPicture(PicturePainter* painter, PictureContainer& pc) +{ + // TODO: Support? Not needed? + pc.prerendered.clear(); + GraphicsOperationCollection* picture = new GraphicsOperationCollection(); + WebCore::PlatformGraphicsContextRecording pgc(picture); + WebCore::GraphicsContext gc(&pgc); + painter->paintContents(&gc, pc.area); + return picture; +} +#else +void PicturePile::drawPicture(SkCanvas* canvas, PictureContainer& pc) +{ + canvas->translate(pc.area.x(), pc.area.y()); + pc.picture->draw(canvas); +} + +Picture* PicturePile::recordPicture(PicturePainter* painter, PictureContainer& pc) +{ + /* The ref counting here is a bit unusual. What happens is begin/end recording + * will ref/unref the recording canvas. However, 'canvas' might be pointing + * at an SkNWayCanvas instead of the recording canvas, which needs to be + * unref'd. Thus what we do is ref the recording canvas so that we can + * always unref whatever canvas we have at the end. + */ + SkPicture* picture = new SkPicture(); + SkCanvas* canvas = picture->beginRecording(pc.area.width(), pc.area.height(), + SkPicture::kUsePathBoundsForClip_RecordingFlag); + SkSafeRef(canvas); + canvas->translate(-pc.area.x(), -pc.area.y()); + IntRect drawArea = pc.area; + if (pc.prerendered.get()) { + SkCanvas* prerender = painter->createPrerenderCanvas(pc.prerendered.get()); + if (!prerender) { + ALOGV("Failed to create prerendered for " INT_RECT_FORMAT, + INT_RECT_ARGS(pc.prerendered->area)); + pc.prerendered.clear(); + } else { + drawArea.unite(pc.prerendered->area); + SkNWayCanvas* nwayCanvas = new SkNWayCanvas(drawArea.width(), drawArea.height()); + nwayCanvas->translate(-drawArea.x(), -drawArea.y()); + nwayCanvas->addCanvas(canvas); + nwayCanvas->addCanvas(prerender); + SkSafeUnref(canvas); + SkSafeUnref(prerender); + canvas = nwayCanvas; + } + } + WebCore::PlatformGraphicsContextSkia pgc(canvas); + WebCore::GraphicsContext gc(&pgc); + ALOGV("painting picture: " INT_RECT_FORMAT, INT_RECT_ARGS(drawArea)); + painter->paintContents(&gc, drawArea); + SkSafeUnref(canvas); + picture->endRecording(); + return picture; +} +#endif + } // namespace WebCore diff --git a/Source/WebKit/android/jni/PicturePile.h b/Source/WebKit/android/jni/PicturePile.h index b28a792..bdcf4f5 100644 --- a/Source/WebKit/android/jni/PicturePile.h +++ b/Source/WebKit/android/jni/PicturePile.h @@ -38,7 +38,17 @@ #include <wtf/ThreadSafeRefCounted.h> #include <wtf/Vector.h> +#define USE_RECORDING_CONTEXT false +#if USE_RECORDING_CONTEXT +namespace WebCore { +class GraphicsOperationCollection; +} +typedef WebCore::GraphicsOperationCollection Picture; +#else class SkPicture; +typedef SkPicture Picture; +#endif + class SkCanvas; namespace WebCore { @@ -57,7 +67,7 @@ public: class PictureContainer { public: - SkPicture* picture; + Picture* picture; IntRect area; bool dirty; RefPtr<PrerenderedInval> prerendered; @@ -68,26 +78,14 @@ public: , dirty(true) {} - PictureContainer(const PictureContainer& other) - : picture(other.picture) - , area(other.area) - , dirty(other.dirty) - , prerendered(other.prerendered) - { - SkSafeRef(picture); - } - - ~PictureContainer() - { - SkSafeUnref(picture); - } + PictureContainer(const PictureContainer& other); + ~PictureContainer(); }; class PicturePile { public: PicturePile() {} PicturePile(const PicturePile& other); - PicturePile(SkPicture* picture); const IntSize& size() { return m_size; } @@ -107,8 +105,10 @@ public: private: void applyWebkitInvals(); void updatePicture(PicturePainter* painter, PictureContainer& container); + Picture* recordPicture(PicturePainter* painter, PictureContainer& container); void appendToPile(const IntRect& inval, const IntRect& originalInval = IntRect()); void drawWithClipRecursive(SkCanvas* canvas, SkRegion& clipRegion, int index); + void drawPicture(SkCanvas* canvas, PictureContainer& pc); IntSize m_size; Vector<PictureContainer> m_pile; diff --git a/Source/WebKit/android/jni/ViewStateSerializer.cpp b/Source/WebKit/android/jni/ViewStateSerializer.cpp index 02ddca6..8963837 100644 --- a/Source/WebKit/android/jni/ViewStateSerializer.cpp +++ b/Source/WebKit/android/jni/ViewStateSerializer.cpp @@ -30,6 +30,7 @@ #include "BaseLayerAndroid.h" #include "CreateJavaOutputStreamAdaptor.h" +#include "DumpLayer.h" #include "FixedPositioning.h" #include "ImagesManager.h" #include "IFrameContentLayerAndroid.h" @@ -56,6 +57,68 @@ enum LayerTypes { LTFixedLayerAndroid = 3 }; +#define ID "mID" +#define LEFT "layout:mLeft" +#define TOP "layout:mTop" +#define WIDTH "layout:getWidth()" +#define HEIGHT "layout:getHeight()" + +class HierarchyLayerDumper : public LayerDumper { +public: + HierarchyLayerDumper(SkWStream* stream, int level) + : LayerDumper(level) + , m_stream(stream) + {} + + virtual void beginLayer(const char* className, const LayerAndroid* layerPtr) { + LayerDumper::beginLayer(className, layerPtr); + for (int i = 0; i < m_indentLevel; i++) { + m_stream->writeText(" "); + } + m_stream->writeText(className); + m_stream->writeText("@"); + m_stream->writeHexAsText(layerPtr->uniqueId()); + m_stream->writeText(" "); + + writeHexVal(ID, (int) layerPtr); + writeIntVal(LEFT, layerPtr->getPosition().fX); + writeIntVal(TOP, layerPtr->getPosition().fY); + writeIntVal(WIDTH, layerPtr->getWidth()); + writeIntVal(HEIGHT, layerPtr->getHeight()); + } + + virtual void beginChildren(int childCount) { + m_stream->writeText("\n"); + LayerDumper::beginChildren(childCount); + } + +protected: + virtual void writeEntry(const char* label, const char* value) { + m_stream->writeText(label); + m_stream->writeText("="); + int len = strlen(value); + m_stream->writeDecAsText(len); + m_stream->writeText(","); + m_stream->writeText(value); + m_stream->writeText(" "); + } + +private: + SkWStream* m_stream; +}; + +static void nativeDumpLayerHierarchy(JNIEnv* env, jobject, jint jbaseLayer, jint level, + jobject jstream, jbyteArray jstorage) +{ + SkWStream *stream = CreateJavaOutputStreamAdaptor(env, jstream, jstorage); + BaseLayerAndroid* baseLayer = reinterpret_cast<BaseLayerAndroid*>(jbaseLayer); + SkSafeRef(baseLayer); + HierarchyLayerDumper dumper(stream, level); + baseLayer->dumpLayers(&dumper); + SkSafeUnref(baseLayer); + delete stream; +} + static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer, jobject jstream, jbyteArray jstorage) { @@ -478,6 +541,8 @@ LayerAndroid* deserializeLayer(int version, SkStream* stream) * JNI registration */ static JNINativeMethod gSerializerMethods[] = { + { "nativeDumpLayerHierarchy", "(IILjava/io/OutputStream;[B)V", + (void*) nativeDumpLayerHierarchy }, { "nativeSerializeViewState", "(ILjava/io/OutputStream;[B)Z", (void*) nativeSerializeViewState }, { "nativeDeserializeViewState", "(ILjava/io/InputStream;[B)I", diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp index 4ce3d8e..4cd39f6 100644 --- a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -50,6 +50,7 @@ #include "FrameLoadRequest.h" #include "FrameTree.h" #include "FrameView.h" +#include "GeolocationClientAndroid.h" #include "GraphicsContext.h" #include "HistoryItem.h" #include "HTMLCollection.h" @@ -497,15 +498,9 @@ WebFrame::loadStarted(WebCore::Frame* frame) if (favicon) env->DeleteLocalRef(favicon); - // Inform the client that the main frame has started a new load. - if (isMainFrame && mPage) { - Chrome* chrome = mPage->chrome(); - if (chrome) { - ChromeClientAndroid* client = static_cast<ChromeClientAndroid*>(chrome->client()); - if (client) - client->onMainFrameLoadStarted(); - } - } + // The main frame has started a new load. + if (isMainFrame && mPage) + WebViewCore::getWebViewCore(mPage->mainFrame()->view())->geolocationManager()->resetRealClientTemporaryPermissionStates(); } void @@ -1099,6 +1094,7 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss EditorClientAndroid* editorC = new EditorClientAndroid; DeviceMotionClientAndroid* deviceMotionC = new DeviceMotionClientAndroid; DeviceOrientationClientAndroid* deviceOrientationC = new DeviceOrientationClientAndroid; + GeolocationClientAndroid* geolocationC = new GeolocationClientAndroid; WebCore::Page::PageClients pageClients; pageClients.chromeClient = chromeC; @@ -1108,6 +1104,7 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss pageClients.inspectorClient = new InspectorClientAndroid; pageClients.deviceMotionClient = deviceMotionC; pageClients.deviceOrientationClient = deviceOrientationC; + pageClients.geolocationClient = geolocationC; WebCore::Page* page = new WebCore::Page(pageClients); editorC->setPage(page); @@ -1150,6 +1147,7 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss frame->page()->focusController()->setFocused(true); deviceMotionC->setWebViewCore(webViewCore); deviceOrientationC->setWebViewCore(webViewCore); + geolocationC->setWebViewCore(webViewCore); // Allow local access to file:/// and substitute data WebCore::SecurityOrigin::setLocalLoadPolicy( diff --git a/Source/WebKit/android/jni/WebHistory.cpp b/Source/WebKit/android/jni/WebHistory.cpp index b6972e4..baafa00 100644 --- a/Source/WebKit/android/jni/WebHistory.cpp +++ b/Source/WebKit/android/jni/WebHistory.cpp @@ -60,19 +60,19 @@ static void writeItem(WTF::Vector<char>& vector, WebCore::HistoryItem* item); static void writeChildrenRecursive(WTF::Vector<char>& vector, WebCore::HistoryItem* parent); static bool readItemRecursive(WebCore::HistoryItem* child, const char** pData, int length); -// Field ids for WebHistoryItems -struct WebHistoryItemFields { +// Field ids for WebHistoryClassicItems +struct WebHistoryItemClassicFields { jmethodID mInit; -} gWebHistoryItem; +} gWebHistoryItemClassic; -struct WebBackForwardListFields { +struct WebBackForwardListClassicFields { jmethodID mAddHistoryItem; jmethodID mRemoveHistoryItem; jmethodID mSetCurrentIndex; -} gWebBackForwardList; +} gWebBackForwardListClassic; //-------------------------------------------------------------------------- -// WebBackForwardList native methods. +// WebBackForwardListClassic native methods. //-------------------------------------------------------------------------- static void WebHistoryClose(JNIEnv* env, jobject obj, jint frame) @@ -398,9 +398,9 @@ void WebHistory::AddItem(const AutoJObject& list, WebCore::HistoryItem* item) WebHistoryItem* bridge = new WebHistoryItem(item); bridge->setActive(); item->setBridge(bridge); - // Allocate a blank WebHistoryItem - jclass clazz = env->FindClass("android/webkit/WebHistoryItem"); - jobject newItem = env->NewObject(clazz, gWebHistoryItem.mInit, + // Allocate a blank WebHistoryItemClassic + jclass clazz = env->FindClass("android/webkit/WebHistoryItemClassic"); + jobject newItem = env->NewObject(clazz, gWebHistoryItemClassic.mInit, reinterpret_cast<int>(bridge)); env->DeleteLocalRef(clazz); @@ -409,7 +409,7 @@ void WebHistory::AddItem(const AutoJObject& list, WebCore::HistoryItem* item) bridge->updateHistoryItem(item); // Add it to the list. - env->CallVoidMethod(list.get(), gWebBackForwardList.mAddHistoryItem, newItem); + env->CallVoidMethod(list.get(), gWebBackForwardListClassic.mAddHistoryItem, newItem); // Delete our local reference. env->DeleteLocalRef(newItem); @@ -418,13 +418,13 @@ void WebHistory::AddItem(const AutoJObject& list, WebCore::HistoryItem* item) void WebHistory::RemoveItem(const AutoJObject& list, int index) { if (list.get()) - list.env()->CallVoidMethod(list.get(), gWebBackForwardList.mRemoveHistoryItem, index); + list.env()->CallVoidMethod(list.get(), gWebBackForwardListClassic.mRemoveHistoryItem, index); } void WebHistory::UpdateHistoryIndex(const AutoJObject& list, int newIndex) { if (list.get()) - list.env()->CallVoidMethod(list.get(), gWebBackForwardList.mSetCurrentIndex, newIndex); + list.env()->CallVoidMethod(list.get(), gWebBackForwardListClassic.mSetCurrentIndex, newIndex); } static void writeString(WTF::Vector<char>& vector, const WTF::String& str) @@ -945,14 +945,14 @@ static void unitTest() //--------------------------------------------------------- // JNI registration //--------------------------------------------------------- -static JNINativeMethod gWebBackForwardListMethods[] = { +static JNINativeMethod gWebBackForwardListClassicMethods[] = { { "nativeClose", "(I)V", (void*) WebHistoryClose }, { "restoreIndex", "(II)V", (void*) WebHistoryRestoreIndex } }; -static JNINativeMethod gWebHistoryItemMethods[] = { +static JNINativeMethod gWebHistoryItemClassicMethods[] = { { "inflate", "(I[B)I", (void*) WebHistoryInflate }, { "nativeRef", "(I)V", @@ -978,31 +978,30 @@ int registerWebHistory(JNIEnv* env) #ifdef UNIT_TEST unitTest(); #endif - // Find WebHistoryItem, its constructor, and the update method. - jclass clazz = env->FindClass("android/webkit/WebHistoryItem"); - ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebHistoryItem"); - gWebHistoryItem.mInit = env->GetMethodID(clazz, "<init>", "(I)V"); - ALOG_ASSERT(gWebHistoryItem.mInit, "Could not find WebHistoryItem constructor"); - + // Find WebHistoryItemClassic, its constructor, and the update method. + jclass clazz = env->FindClass("android/webkit/WebHistoryItemClassic"); + ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebHistoryItemClassic"); + gWebHistoryItemClassic.mInit = env->GetMethodID(clazz, "<init>", "(I)V"); + ALOG_ASSERT(gWebHistoryItemClassic.mInit, "Could not find WebHistoryItemClassic constructor"); env->DeleteLocalRef(clazz); - // Find the WebBackForwardList object and method. - clazz = env->FindClass("android/webkit/WebBackForwardList"); - ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebBackForwardList"); - gWebBackForwardList.mAddHistoryItem = env->GetMethodID(clazz, "addHistoryItem", + // Find the WebBackForwardListClassic object and method. + clazz = env->FindClass("android/webkit/WebBackForwardListClassic"); + ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebBackForwardListClassic"); + gWebBackForwardListClassic.mAddHistoryItem = env->GetMethodID(clazz, "addHistoryItem", "(Landroid/webkit/WebHistoryItem;)V"); - ALOG_ASSERT(gWebBackForwardList.mAddHistoryItem, "Could not find method addHistoryItem"); - gWebBackForwardList.mRemoveHistoryItem = env->GetMethodID(clazz, "removeHistoryItem", + ALOG_ASSERT(gWebBackForwardListClassic.mAddHistoryItem, "Could not find method addHistoryItem"); + gWebBackForwardListClassic.mRemoveHistoryItem = env->GetMethodID(clazz, "removeHistoryItem", "(I)V"); - ALOG_ASSERT(gWebBackForwardList.mRemoveHistoryItem, "Could not find method removeHistoryItem"); - gWebBackForwardList.mSetCurrentIndex = env->GetMethodID(clazz, "setCurrentIndex", "(I)V"); - ALOG_ASSERT(gWebBackForwardList.mSetCurrentIndex, "Could not find method setCurrentIndex"); + ALOG_ASSERT(gWebBackForwardListClassic.mRemoveHistoryItem, "Could not find method removeHistoryItem"); + gWebBackForwardListClassic.mSetCurrentIndex = env->GetMethodID(clazz, "setCurrentIndex", "(I)V"); + ALOG_ASSERT(gWebBackForwardListClassic.mSetCurrentIndex, "Could not find method setCurrentIndex"); env->DeleteLocalRef(clazz); - int result = jniRegisterNativeMethods(env, "android/webkit/WebBackForwardList", - gWebBackForwardListMethods, NELEM(gWebBackForwardListMethods)); - return (result < 0) ? result : jniRegisterNativeMethods(env, "android/webkit/WebHistoryItem", - gWebHistoryItemMethods, NELEM(gWebHistoryItemMethods)); + int result = jniRegisterNativeMethods(env, "android/webkit/WebBackForwardListClassic", + gWebBackForwardListClassicMethods, NELEM(gWebBackForwardListClassicMethods)); + return (result < 0) ? result : jniRegisterNativeMethods(env, "android/webkit/WebHistoryItemClassic", + gWebHistoryItemClassicMethods, NELEM(gWebHistoryItemClassicMethods)); } } /* namespace android */ diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index f17e573..b0317c06 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -401,7 +401,7 @@ struct WebViewCore::TextFieldInitDataGlue { jfieldID m_maxLength; jfieldID m_contentBounds; jfieldID m_nodeLayerId; - jfieldID m_contentRect; + jfieldID m_clientRect; }; /* @@ -423,7 +423,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m , m_mainFrame(mainframe) , m_popupReply(0) , m_blockTextfieldUpdates(false) - , m_focusBoundsChanged(false) , m_skipContentDraw(false) , m_textGeneration(0) , m_maxXScroll(320/4) @@ -436,7 +435,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m , m_textWrapWidth(320) , m_scale(1.0f) , m_groupForVisitedLinks(0) - , m_isPaused(false) , m_cacheMode(0) , m_fullscreenVideoMode(false) , m_matchCount(0) @@ -446,6 +444,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m , m_screenOnCounter(0) , m_currentNodeDomNavigationAxis(0) , m_deviceMotionAndOrientationManager(this) + , m_geolocationManager(this) #if ENABLE(TOUCH_EVENTS) , m_forwardingTouchEvents(false) #endif @@ -526,7 +525,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_textFieldInitDataGlue->m_maxLength = env->GetFieldID(tfidClazz, "mMaxLength", "I"); m_textFieldInitDataGlue->m_contentBounds = env->GetFieldID(tfidClazz, "mContentBounds", "Landroid/graphics/Rect;"); m_textFieldInitDataGlue->m_nodeLayerId = env->GetFieldID(tfidClazz, "mNodeLayerId", "I"); - m_textFieldInitDataGlue->m_contentRect = env->GetFieldID(tfidClazz, "mContentRect", "Landroid/graphics/Rect;"); + m_textFieldInitDataGlue->m_clientRect = env->GetFieldID(tfidClazz, "mClientRect", "Landroid/graphics/Rect;"); m_textFieldInitDataGlue->m_constructor = GetJMethod(env, tfidClazz, "<init>", "()V"); env->DeleteLocalRef(tfidClazz); @@ -728,13 +727,6 @@ void WebViewCore::clearContent() updateLocale(); } -bool WebViewCore::focusBoundsChanged() -{ - bool result = m_focusBoundsChanged; - m_focusBoundsChanged = false; - return result; -} - void WebViewCore::paintContents(WebCore::GraphicsContext* gc, WebCore::IntRect& dirty) { WebCore::FrameView* view = m_mainFrame->view(); @@ -1507,6 +1499,7 @@ bool WebViewCore::selectWordAroundPosition(Frame* frame, VisiblePosition pos) VisibleSelection selection(pos); selection.expandUsingGranularity(WordGranularity); SelectionController* selectionController = frame->selection(); + selection = VisibleSelection(selection.start(), selection.end()); bool wordSelected = false; if (selectionController->shouldChangeSelection(selection)) { @@ -1566,7 +1559,8 @@ void WebViewCore::layerToAbsoluteOffset(const LayerAndroid* layer, IntPoint& off void WebViewCore::setSelectionCaretInfo(SelectText* selectTextContainer, const WebCore::Position& pos, const IntPoint& frameOffset, - SelectText::HandleId handleId, int caretRectOffset, EAffinity affinity) + SelectText::HandleId handleId, SelectText::HandleType handleType, + int caretRectOffset, EAffinity affinity) { Node* node = pos.anchorNode(); LayerAndroid* layer = 0; @@ -1584,6 +1578,7 @@ void WebViewCore::setSelectionCaretInfo(SelectText* selectTextContainer, caretRect.setX(absoluteOffset.x() - offset.x() + caretRectOffset); caretRect.setY(absoluteOffset.y() - offset.y()); selectTextContainer->setCaretRect(handleId, caretRect); + selectTextContainer->setHandleType(handleId, handleType); selectTextContainer->setTextRect(handleId, positionToTextRect(pos, affinity, offset)); } @@ -1601,14 +1596,28 @@ bool WebViewCore::isLtr(const Position& position) return isLtr; } +static Node* findInputParent(Node* node) +{ + Node* testNode = node; + while (testNode) { + RenderObject* renderer = testNode->renderer(); + if (renderer + && (renderer->isTextArea() || renderer->isTextControl())) { + return testNode; + } + testNode = testNode->parentOrHostNode(); + } + return node; +} + SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) { bool isCaret = selection.isCaret(); + Position base = selection.base(); + Position extent = selection.extent(); if (selection.isNone() || (!selection.isContentEditable() && isCaret) - || !selection.start().anchorNode() - || !selection.start().anchorNode()->renderer() - || !selection.end().anchorNode() - || !selection.end().anchorNode()->renderer()) + || !base.anchorNode() || !base.anchorNode()->renderer() + || !extent.anchorNode() || !extent.anchorNode()->renderer()) return 0; RefPtr<Range> range = selection.firstRange(); @@ -1624,20 +1633,39 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) IntPoint frameOffset = convertGlobalContentToFrameContent(IntPoint()); SelectText* selectTextContainer = new SelectText(); if (isCaret) { - setSelectionCaretInfo(selectTextContainer, selection.start(), frameOffset, - SelectText::LeftHandle, 0, selection.affinity()); - setSelectionCaretInfo(selectTextContainer, selection.start(), frameOffset, - SelectText::RightHandle, 0, selection.affinity()); + setSelectionCaretInfo(selectTextContainer, base, frameOffset, + SelectText::BaseHandle, SelectText::CenterHandle, 0, + selection.affinity()); + setSelectionCaretInfo(selectTextContainer, base, frameOffset, + SelectText::ExtentHandle, SelectText::CenterHandle, 0, + selection.affinity()); } else { - bool ltr = isLtr(selection.start()); - Position left = ltr ? selection.start() : selection.end(); - Position right = ltr ? selection.end() : selection.start(); - int leftOffset = isLtr(left) ? 0 : -1; - int rightOffset = isLtr(right) ? 0 : -1; - setSelectionCaretInfo(selectTextContainer, left, frameOffset, - SelectText::LeftHandle, leftOffset, selection.affinity()); - setSelectionCaretInfo(selectTextContainer, right, frameOffset, - SelectText::RightHandle, rightOffset, selection.affinity()); + bool isBaseLtr = isLtr(base); + bool isBaseStart = comparePositions(base, extent) <= 0; + int baseOffset = isBaseLtr ? 0 : -1; + SelectText::HandleType baseHandleType = (isBaseLtr == isBaseStart) + ? SelectText::LeftHandle : SelectText::RightHandle; + EAffinity affinity = selection.affinity(); + setSelectionCaretInfo(selectTextContainer, base, frameOffset, + SelectText::BaseHandle, baseHandleType, baseOffset, affinity); + bool isExtentLtr = isLtr(extent); + int extentOffset = isExtentLtr ? 0 : -1; + SelectText::HandleType extentHandleType = (isExtentLtr == isBaseStart) + ? SelectText::RightHandle : SelectText::LeftHandle; + setSelectionCaretInfo(selectTextContainer, extent, frameOffset, + SelectText::ExtentHandle, extentHandleType, extentOffset, affinity); + IntRect clipRect; + if (selection.isContentEditable()) { + Node* editable = findInputParent(base.anchorNode()); + RenderObject* render = editable->renderer(); + if (render && render->isBox() && !render->isBody()) { + RenderBox* renderBox = toRenderBox(render); + clipRect = renderBox->clientBoxRect(); + FloatPoint pos = renderBox->localToAbsolute(clipRect.location()); + clipRect.setX(pos.x()); + clipRect.setY(pos.y()); + } + } Node* stopNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) { @@ -1651,7 +1679,8 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) int layerId = platformLayerIdFromNode(node, &layer); Vector<IntRect> rects; renderText->absoluteRectsForRange(rects, startOffset, endOffset, true); - selectTextContainer->addHighlightRegion(layer, rects, frameOffset); + selectTextContainer->addHighlightRegion(layer, rects, frameOffset, + clipRect); } } selectTextContainer->setText(range->text()); @@ -1697,25 +1726,25 @@ IntPoint WebViewCore::convertGlobalContentToFrameContent(const IntPoint& point, return IntPoint(point.x() + frameOffset.x(), point.y() + frameOffset.y()); } -Position WebViewCore::trimSelectionPosition(const Position &start, const Position& stop) +VisiblePosition WebViewCore::trimSelectionPosition(const VisiblePosition &start, + const VisiblePosition& stop) { int direction = comparePositions(start, stop); if (direction == 0) return start; bool forward = direction < 0; - EAffinity affinity = forward ? DOWNSTREAM : UPSTREAM; bool move; - Position pos = start; + VisiblePosition pos = start; bool movedTooFar = false; do { move = true; - Node* node = pos.anchorNode(); + Node* node = pos.deepEquivalent().anchorNode(); if (node && node->isTextNode() && node->renderer()) { RenderText *textRenderer = toRenderText(node->renderer()); move = !textRenderer->textLength(); } if (move) { - Position nextPos = forward ? pos.next() : pos.previous(); + VisiblePosition nextPos = forward ? pos.next() : pos.previous(); movedTooFar = nextPos.isNull() || pos == nextPos || ((comparePositions(nextPos, stop) < 0) != forward); pos = nextPos; @@ -1726,47 +1755,65 @@ Position WebViewCore::trimSelectionPosition(const Position &start, const Positio return pos; } -void WebViewCore::selectText(int startX, int startY, int endX, int endY) +void WebViewCore::selectText(SelectText::HandleId handleId, int x, int y) { SelectionController* sc = focusedFrame()->selection(); - IntPoint startPoint = convertGlobalContentToFrameContent(IntPoint(startX, startY)); - VisiblePosition startPosition(visiblePositionForContentPoint(startPoint)); - IntPoint endPoint = convertGlobalContentToFrameContent(IntPoint(endX, endY)); - VisiblePosition endPosition(visiblePositionForContentPoint(endPoint)); + VisibleSelection selection = sc->selection(); + Position base = selection.base(); + Position extent = selection.extent(); + IntPoint dragPoint = convertGlobalContentToFrameContent(IntPoint(x, y)); + VisiblePosition dragPosition(visiblePositionForContentPoint(dragPoint)); - if (startPosition.isNull() || endPosition.isNull()) + if (base.isNull() || extent.isNull() || dragPosition.isNull()) return; + bool draggingBase = (handleId == SelectText::BaseHandle); + if (draggingBase) + base = dragPosition.deepEquivalent(); + else + extent = dragPosition.deepEquivalent(); - // Ensure startPosition is before endPosition - if (comparePositions(startPosition, endPosition) > 0) - swap(startPosition, endPosition); + bool baseIsStart = (comparePositions(base, extent) <= 0); + Position& start = baseIsStart ? base : extent; + Position& end = baseIsStart ? extent : base; + VisiblePosition startPosition(start, selection.affinity()); + VisiblePosition endPosition(end, selection.affinity()); + bool draggingStart = (baseIsStart == draggingBase); - if (sc->isContentEditable()) { - startPosition = sc->selection().visibleStart().honorEditableBoundaryAtOrAfter(startPosition); - endPosition = sc->selection().visibleEnd().honorEditableBoundaryAtOrBefore(endPosition); - if (startPosition.isNull() || endPosition.isNull()) { + if (draggingStart) { + if (selection.isRange()) { + startPosition = trimSelectionPosition(startPosition, endPosition); + if ((startPosition != endPosition) && isEndOfBlock(startPosition)) { + // Ensure startPosition is not at end of block + VisiblePosition nextStartPosition(startPosition.next()); + if (nextStartPosition.isNotNull()) + startPosition = nextStartPosition; + } + } + startPosition = endPosition.honorEditableBoundaryAtOrAfter(startPosition); + if (startPosition.isNull()) return; + start = startPosition.deepEquivalent(); + if (selection.isCaret()) + end = start; + } else { + if (selection.isRange()) { + endPosition = trimSelectionPosition(endPosition, startPosition); + if ((start != end) && isStartOfBlock(endPosition)) { + // Ensure endPosition is not at start of block + VisiblePosition prevEndPosition(endPosition.previous()); + if (!prevEndPosition.isNull()) + endPosition = prevEndPosition; + } } + endPosition = startPosition.honorEditableBoundaryAtOrAfter(endPosition); + if (endPosition.isNull()) + return; + end = endPosition.deepEquivalent(); + if (selection.isCaret()) + start = end; } - // Ensure startPosition is not at end of block - if (startPosition != endPosition && isEndOfBlock(startPosition)) { - VisiblePosition nextStartPosition(startPosition.next()); - if (!nextStartPosition.isNull()) - startPosition = nextStartPosition; - } - // Ensure endPosition is not at start of block - if (startPosition != endPosition && isStartOfBlock(endPosition)) { - VisiblePosition prevEndPosition(endPosition.previous()); - if (!prevEndPosition.isNull()) - endPosition = prevEndPosition; - } - - Position start = startPosition.deepEquivalent(); - Position end = endPosition.deepEquivalent(); - start = trimSelectionPosition(start, end); - end = trimSelectionPosition(end, start); - VisibleSelection selection(start, end); + selection = VisibleSelection(base, extent); // Only allow changes between caret positions or to text selection. bool selectChangeAllowed = (!selection.isCaret() || sc->isCaret()); if (selectChangeAllowed && sc->shouldChangeSelection(selection)) @@ -2950,27 +2997,25 @@ void WebViewCore::passToJs(int generation, const WTF::String& current, updateTextSelection(); } -WebCore::IntRect WebViewCore::scrollFocusedTextInput(float xPercent, int y) +void WebViewCore::scrollFocusedTextInput(float xPercent, int y) { WebCore::Node* focus = currentFocus(); if (!focus) { clearTextEntry(); - return WebCore::IntRect(); + return; } WebCore::RenderTextControl* renderText = toRenderTextControl(focus); if (!renderText) { clearTextEntry(); - return WebCore::IntRect(); + return; } - int x = (int) (xPercent * (renderText->scrollWidth() - + int x = (int)round(xPercent * (renderText->scrollWidth() - renderText->clientWidth())); renderText->setScrollLeft(x); renderText->setScrollTop(y); focus->document()->frame()->selection()->recomputeCaretRect(); - LayerAndroid* layer = 0; - platformLayerIdFromNode(focus, &layer); - return absoluteContentRect(focus, layer); + updateTextSelection(); } void WebViewCore::setFocusControllerActive(bool active) @@ -3364,10 +3409,10 @@ bool WebViewCore::isAutoCompleteEnabled(Node* node) return isEnabled; } -WebCore::IntRect WebViewCore::absoluteContentRect(WebCore::Node* node, +WebCore::IntRect WebViewCore::absoluteClientRect(WebCore::Node* node, LayerAndroid* layer) { - IntRect contentRect; + IntRect clientRect; if (node) { RenderObject* render = node->renderer(); if (render && render->isBox() && !render->isBody()) { @@ -3376,11 +3421,12 @@ WebCore::IntRect WebViewCore::absoluteContentRect(WebCore::Node* node, WebViewCore::layerToAbsoluteOffset(layer, offset); RenderBox* renderBox = toRenderBox(render); - contentRect = renderBox->absoluteContentBox(); - contentRect.move(-offset.x(), -offset.y()); + clientRect = renderBox->clientBoxRect(); + FloatPoint absPos = renderBox->localToAbsolute(FloatPoint()); + clientRect.move(absPos.x() - offset.x(), absPos.y() - offset.y()); } } - return contentRect; + return clientRect; } jobject WebViewCore::createTextFieldInitData(Node* node) @@ -3417,7 +3463,7 @@ jobject WebViewCore::createTextFieldInitData(Node* node) env->SetIntField(initData, classDef->m_maxLength, getMaxLength(node)); LayerAndroid* layer = 0; int layerId = platformLayerIdFromNode(node, &layer); - IntRect bounds = absoluteContentRect(node, layer); + IntRect bounds = absoluteClientRect(node, layer); ScopedLocalRef<jobject> jbounds(env, intRectToRect(env, bounds)); env->SetObjectField(initData, classDef->m_contentBounds, jbounds.get()); env->SetIntField(initData, classDef->m_nodeLayerId, layerId); @@ -3429,7 +3475,7 @@ jobject WebViewCore::createTextFieldInitData(Node* node) contentRect.move(-rtc->scrollLeft(), -rtc->scrollTop()); } ScopedLocalRef<jobject> jcontentRect(env, intRectToRect(env, contentRect)); - env->SetObjectField(initData, classDef->m_contentRect, jcontentRect.get()); + env->SetObjectField(initData, classDef->m_clientRect, jcontentRect.get()); return initData; } @@ -4505,12 +4551,10 @@ static void PassToJs(JNIEnv* env, jobject obj, jint nativeClass, } static void ScrollFocusedTextInput(JNIEnv* env, jobject obj, jint nativeClass, - jfloat xPercent, jint y, jobject contentBounds) + jfloat xPercent, jint y) { WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); - IntRect bounds = viewImpl->scrollFocusedTextInput(xPercent, y); - if (contentBounds) - GraphicsJNI::irect_to_jrect(bounds, env, contentBounds); + viewImpl->scrollFocusedTextInput(xPercent, y); } static void SetFocusControllerActive(JNIEnv* env, jobject obj, jint nativeClass, @@ -4765,10 +4809,7 @@ static void GeolocationPermissionsProvide(JNIEnv* env, jobject obj, jint nativeClass, jstring origin, jboolean allow, jboolean remember) { WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); - Frame* frame = viewImpl->mainFrame(); - - ChromeClientAndroid* chromeClient = static_cast<ChromeClientAndroid*>(frame->page()->chrome()->client()); - chromeClient->provideGeolocationPermissions(jstringToWtfString(env, origin), allow, remember); + viewImpl->geolocationManager()->provideRealClientPermissionState(jstringToWtfString(env, origin), allow, remember); } static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jint nativeClass, @@ -4777,20 +4818,6 @@ static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jint nativeClass, WebCore::SchemeRegistry::registerURLSchemeAsLocal(jstringToWtfString(env, scheme)); } -static bool FocusBoundsChanged(JNIEnv* env, jobject obj, jint nativeClass) -{ - return reinterpret_cast<WebViewCore*>(nativeClass)->focusBoundsChanged(); -} - -static void SetIsPaused(JNIEnv* env, jobject obj, jint nativeClass, - jboolean isPaused) -{ - // tell the webcore thread to stop thinking while we do other work - // (selection and scrolling). This has nothing to do with the lifecycle - // pause and resume. - reinterpret_cast<WebViewCore*>(nativeClass)->setIsPaused(isPaused); -} - static void Pause(JNIEnv* env, jobject obj, jint nativeClass) { // This is called for the foreground tab when the browser is put to the @@ -4798,50 +4825,36 @@ static void Pause(JNIEnv* env, jobject obj, jint nativeClass) // browser). The browser can only be killed by the system when it is in the // background, so saving the Geolocation permission state now ensures that // is maintained when the browser is killed. - WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); - ChromeClient* chromeClient = viewImpl->mainFrame()->page()->chrome()->client(); - ChromeClientAndroid* chromeClientAndroid = static_cast<ChromeClientAndroid*>(chromeClient); - chromeClientAndroid->storeGeolocationPermissions(); + GeolocationPermissions::maybeStorePermanentPermissions(); + WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); Frame* mainFrame = viewImpl->mainFrame(); - for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) { - Geolocation* geolocation = frame->domWindow()->navigator()->optionalGeolocation(); - if (geolocation) - geolocation->suspend(); - } if (mainFrame) mainFrame->settings()->setMinDOMTimerInterval(BACKGROUND_TIMER_INTERVAL); viewImpl->deviceMotionAndOrientationManager()->maybeSuspendClients(); + viewImpl->geolocationManager()->suspendRealClient(); ANPEvent event; SkANP::InitEvent(&event, kLifecycle_ANPEventType); event.data.lifecycle.action = kPause_ANPLifecycleAction; viewImpl->sendPluginEvent(event); - - viewImpl->setIsPaused(true); } static void Resume(JNIEnv* env, jobject obj, jint nativeClass) { WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); Frame* mainFrame = viewImpl->mainFrame(); - for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) { - Geolocation* geolocation = frame->domWindow()->navigator()->optionalGeolocation(); - if (geolocation) - geolocation->resume(); - } if (mainFrame) mainFrame->settings()->setMinDOMTimerInterval(FOREGROUND_TIMER_INTERVAL); viewImpl->deviceMotionAndOrientationManager()->maybeResumeClients(); + viewImpl->geolocationManager()->resumeRealClient(); ANPEvent event; SkANP::InitEvent(&event, kLifecycle_ANPEventType); event.data.lifecycle.action = kResume_ANPLifecycleAction; viewImpl->sendPluginEvent(event); - - viewImpl->setIsPaused(false); } static void FreeMemory(JNIEnv* env, jobject obj, jint nativeClass) @@ -4959,10 +4972,10 @@ static jobject GetText(JNIEnv* env, jobject obj, jint nativeClass, } static void SelectText(JNIEnv* env, jobject obj, jint nativeClass, - jint startX, jint startY, jint endX, jint endY) + jint handleId, jint x, jint y) { WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); - viewImpl->selectText(startX, startY, endX, endY); + viewImpl->selectText(static_cast<SelectText::HandleId>(handleId), x, y); } static void ClearSelection(JNIEnv* env, jobject obj, jint nativeClass) @@ -5006,8 +5019,6 @@ static int FindNext(JNIEnv* env, jobject obj, jint nativeClass, static JNINativeMethod gJavaWebViewCoreMethods[] = { { "nativeClearContent", "(I)V", (void*) ClearContent }, - { "nativeFocusBoundsChanged", "(I)Z", - (void*) FocusBoundsChanged } , { "nativeKey", "(IIIIZZZZ)Z", (void*) Key }, { "nativeContentInvalidateAll", "(I)V", @@ -5034,7 +5045,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) MoveMouse }, { "passToJs", "(IILjava/lang/String;IIZZZZ)V", (void*) PassToJs }, - { "nativeScrollFocusedTextInput", "(IFILandroid/graphics/Rect;)V", + { "nativeScrollFocusedTextInput", "(IFI)V", (void*) ScrollFocusedTextInput }, { "nativeSetFocusControllerActive", "(IZ)V", (void*) SetFocusControllerActive }, @@ -5072,7 +5083,6 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) SetNewStorageLimit }, { "nativeGeolocationPermissionsProvide", "(ILjava/lang/String;ZZ)V", (void*) GeolocationPermissionsProvide }, - { "nativeSetIsPaused", "(IZ)V", (void*) SetIsPaused }, { "nativePause", "(I)V", (void*) Pause }, { "nativeResume", "(I)V", (void*) Resume }, { "nativeFreeMemory", "(I)V", (void*) FreeMemory }, @@ -5100,7 +5110,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) InsertText }, { "nativeGetText", "(IIIII)Ljava/lang/String;", (void*) GetText }, - { "nativeSelectText", "(IIIII)V", + { "nativeSelectText", "(IIII)V", (void*) SelectText }, { "nativeClearTextSelection", "(I)V", (void*) ClearSelection }, diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h index 5264f7f..def09d7 100644 --- a/Source/WebKit/android/jni/WebViewCore.h +++ b/Source/WebKit/android/jni/WebViewCore.h @@ -30,6 +30,7 @@ #include "DOMSelection.h" #include "FileChooser.h" #include "FocusDirection.h" +#include "GeolocationManager.h" #include "HitTestResult.h" #include "PicturePile.h" #include "PlatformGraphicsContext.h" @@ -396,7 +397,7 @@ namespace android { /** * Scroll the focused textfield to (x, y) in document space */ - WebCore::IntRect scrollFocusedTextInput(float x, int y); + void scrollFocusedTextInput(float x, int y); /** * Set the FocusController's active and focused states, so that * the caret will draw (true) or not. @@ -508,8 +509,6 @@ namespace android { // reset the picture set to empty void clearContent(); - bool focusBoundsChanged(); - // record content in a new BaseLayerAndroid, copying the layer tree as well WebCore::BaseLayerAndroid* recordContent(SkIPoint* ); @@ -546,12 +545,11 @@ namespace android { void setWebTextViewAutoFillable(int queryId, const string16& previewSummary); DeviceMotionAndOrientationManager* deviceMotionAndOrientationManager() { return &m_deviceMotionAndOrientationManager; } + GeolocationManager* geolocationManager() { return &m_geolocationManager; } void listBoxRequest(WebCoreReply* reply, const uint16_t** labels, size_t count, const int enabled[], size_t enabledCount, bool multiple, const int selected[], size_t selectedCountOrSelection); - bool isPaused() const { return m_isPaused; } - void setIsPaused(bool isPaused) { m_isPaused = isPaused; } bool drawIsPaused() const; // The actual content (without title bar) size in doc coordinate int screenWidth() const { return m_screenWidth; } @@ -580,7 +578,7 @@ namespace android { int startX, int startY, int endX, int endY); static int platformLayerIdFromNode(WebCore::Node* node, WebCore::LayerAndroid** outLayer = 0); - void selectText(int startX, int startY, int endX, int endY); + void selectText(SelectText::HandleId handleId, int x, int y); bool selectWordAt(int x, int y); // Converts from the global content coordinates that WebView sends @@ -728,18 +726,19 @@ namespace android { void setSelectionCaretInfo(SelectText* selectTextContainer, const WebCore::Position& position, const WebCore::IntPoint& frameOffset, - SelectText::HandleId handleId, int offset, - EAffinity affinity); + SelectText::HandleId handleId, SelectText::HandleType handleType, + int offset, EAffinity affinity); static int getMaxLength(WebCore::Node* node); static WTF::String getFieldName(WebCore::Node* node); static bool isAutoCompleteEnabled(WebCore::Node* node); - WebCore::IntRect absoluteContentRect(WebCore::Node* node, + WebCore::IntRect absoluteClientRect(WebCore::Node* node, WebCore::LayerAndroid* layer); static WebCore::IntRect positionToTextRect(const WebCore::Position& position, WebCore::EAffinity affinity, const WebCore::IntPoint& offset); static bool isLtr(const WebCore::Position& position); - static WebCore::Position trimSelectionPosition( - const WebCore::Position& start, const WebCore::Position& stop); + static WebCore::VisiblePosition trimSelectionPosition( + const WebCore::VisiblePosition& start, + const WebCore::VisiblePosition& stop); // called from constructor, to add this to a global list static void addInstance(WebViewCore*); @@ -759,7 +758,6 @@ namespace android { // Used in passToJS to avoid updating the UI text field until after the // key event has been processed. bool m_blockTextfieldUpdates; - bool m_focusBoundsChanged; bool m_skipContentDraw; // Passed in with key events to know when they were generated. Store it // with the cache so that we can ignore stale text changes. @@ -782,7 +780,6 @@ namespace android { int m_textWrapWidth; float m_scale; WebCore::PageGroup* m_groupForVisitedLinks; - bool m_isPaused; int m_cacheMode; bool m_fullscreenVideoMode; @@ -801,6 +798,7 @@ namespace android { int m_screenOnCounter; WebCore::Node* m_currentNodeDomNavigationAxis; DeviceMotionAndOrientationManager m_deviceMotionAndOrientationManager; + GeolocationManager m_geolocationManager; #if ENABLE(TOUCH_EVENTS) bool m_forwardingTouchEvents; diff --git a/Source/WebKit/android/nav/DrawExtra.cpp b/Source/WebKit/android/nav/DrawExtra.cpp index 2f57dc1..a7d686c 100644 --- a/Source/WebKit/android/nav/DrawExtra.cpp +++ b/Source/WebKit/android/nav/DrawExtra.cpp @@ -52,7 +52,8 @@ SkRegion* RegionLayerDrawExtra::getHighlightRegionsForLayer(const LayerAndroid* } void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects, - const IntPoint& additionalOffset) + const IntPoint& additionalOffset, + const IntRect& clipRect) { if (rects.isEmpty()) return; @@ -66,6 +67,11 @@ void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const V WebViewCore::layerToAbsoluteOffset(layer, offset); for (size_t i = 0; i < rects.size(); i++) { IntRect r = rects.at(i); + if (!clipRect.isEmpty()) { + r.intersect(clipRect); + if (r.isEmpty()) + continue; // don't add it to the region + } r.move(-offset.x(), -offset.y()); region->op(r.x(), r.y(), r.maxX(), r.maxY(), SkRegion::kUnion_Op); } diff --git a/Source/WebKit/android/nav/DrawExtra.h b/Source/WebKit/android/nav/DrawExtra.h index cc94476..1850b6b 100644 --- a/Source/WebKit/android/nav/DrawExtra.h +++ b/Source/WebKit/android/nav/DrawExtra.h @@ -65,7 +65,8 @@ public: virtual ~RegionLayerDrawExtra(); void addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects, - const IntPoint& additionalOffset = IntPoint()); + const IntPoint& additionalOffset = IntPoint(), + const IntRect& clipRect = IntRect()); virtual void draw(SkCanvas*, LayerAndroid*); virtual void drawGL(GLExtras*, const LayerAndroid*); diff --git a/Source/WebKit/android/nav/SelectText.h b/Source/WebKit/android/nav/SelectText.h index aaaf3bb..8f7592d 100644 --- a/Source/WebKit/android/nav/SelectText.h +++ b/Source/WebKit/android/nav/SelectText.h @@ -35,8 +35,13 @@ namespace android { class SelectText : public RegionLayerDrawExtra { public: enum HandleId { + BaseHandle = 0, + ExtentHandle = 1, + }; + enum HandleType { LeftHandle = 0, - RightHandle = 1, + CenterHandle = 1, + RightHandle = 2, }; IntRect& caretRect(HandleId id) { return m_caretRects[id]; } @@ -48,11 +53,14 @@ public: void setText(const String& text) { m_text = text.threadsafeCopy(); } String& getText() { return m_text; } + HandleType getHandleType(HandleId id) { return m_handleType[id]; } + void setHandleType(HandleId id, HandleType type) { m_handleType[id] = type; } private: IntRect m_caretRects[2]; IntRect m_textRects[2]; int m_caretLayerId[2]; + HandleType m_handleType[2]; String m_text; }; diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index a67b5fd..c708c25 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -32,6 +32,7 @@ #include "BaseLayerAndroid.h" #include "BaseRenderer.h" #include "DrawExtra.h" +#include "DumpLayer.h" #include "Frame.h" #include "GLWebViewState.h" #include "GraphicsJNI.h" @@ -716,7 +717,7 @@ void findMaxVisibleRect(int movingLayerId, SkIRect& visibleContentRect) if (findMaskedRectsForLayer(m_baseLayer, rects, movingLayerId)) { float maxSize = 0.0; const FloatRect* largest = 0; - for (int i = 0; i < rects.size(); i++) { + for (unsigned int i = 0; i < rects.size(); i++) { const FloatRect& rect = rects[i]; float size = rect.width() * rect.height(); if (size > maxSize) { @@ -731,6 +732,29 @@ void findMaxVisibleRect(int movingLayerId, SkIRect& visibleContentRect) } } +bool isHandleLeft(SelectText::HandleId handleId) +{ + SelectText* selectText = static_cast<SelectText*>(getDrawExtra(DrawExtrasSelection)); + if (!selectText) + return (handleId == SelectText::BaseHandle); + + return (selectText->getHandleType(handleId) == SelectText::LeftHandle); +} + +bool isPointVisible(int layerId, int contentX, int contentY) +{ + bool isVisible = true; + const TransformationMatrix* transform = getLayerTransform(layerId); + if (transform) { + // layer is guaranteed to be non-NULL because of getLayerTransform + LayerAndroid* layer = m_baseLayer->findById(layerId); + IntRect rect = layer->visibleContentArea(); + rect = transform->mapRect(rect); + isVisible = rect.contains(contentX, contentY); + } + return isVisible; +} + private: // local state for WebView bool m_isDrawingPaused; // private to getFrameCache(); other functions operate in a different thread @@ -972,6 +996,28 @@ static void nativeCopyBaseContentToPicture(JNIEnv *env, jobject obj, jobject pic GET_NATIVE_VIEW(env, obj)->copyBaseContentToPicture(picture); } +static jboolean nativeDumpLayerContentToPicture(JNIEnv *env, jobject obj, jint instance, + jstring jclassName, jint layerId, jobject pict) +{ + bool success = false; + SkPicture* picture = GraphicsJNI::getNativePicture(env, pict); + std::string classname = jstringToStdString(env, jclassName); + BaseLayerAndroid* baseLayer = reinterpret_cast<WebView*>(instance)->getBaseLayer(); + LayerAndroid* layer = baseLayer->findById(layerId); + SkSafeRef(layer); + if (layer && layer->subclassName() == classname) { + LayerContent* content = layer->content(); + if (content) { + SkCanvas* canvas = picture->beginRecording(content->width(), content->height()); + content->draw(canvas); + picture->endRecording(); + success = true; + } + } + SkSafeUnref(layer); + return success; +} + static bool nativeHasContent(JNIEnv *env, jobject obj) { return GET_NATIVE_VIEW(env, obj)->hasContent(); @@ -1164,7 +1210,8 @@ static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl) if (baseLayer) { FILE* file = fopen(LAYERS_TREE_LOG_FILE,"w"); if (file) { - baseLayer->dumpLayers(file, 0); + WebCore::FileLayerDumper dumper(file); + baseLayer->dumpLayers(&dumper); fclose(file); } } @@ -1288,6 +1335,20 @@ static void nativeFindMaxVisibleRect(JNIEnv *env, jobject obj, jint nativeView, GraphicsJNI::irect_to_jrect(nativeRect, env, visibleContentRect); } +static bool nativeIsHandleLeft(JNIEnv *env, jobject obj, jint nativeView, + jint handleId) +{ + WebView* webview = reinterpret_cast<WebView*>(nativeView); + return webview->isHandleLeft(static_cast<SelectText::HandleId>(handleId)); +} + +static bool nativeIsPointVisible(JNIEnv *env, jobject obj, jint nativeView, + jint layerId, jint contentX, jint contentY) +{ + WebView* webview = reinterpret_cast<WebView*>(nativeView); + return webview->isPointVisible(layerId, contentX, contentY); +} + /* * JNI registration */ @@ -1318,6 +1379,8 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeGetBaseLayer }, { "nativeCopyBaseContentToPicture", "(Landroid/graphics/Picture;)V", (void*) nativeCopyBaseContentToPicture }, + { "nativeDumpLayerContentToPicture", "(ILjava/lang/String;ILandroid/graphics/Picture;)Z", + (void*) nativeDumpLayerContentToPicture }, { "nativeHasContent", "()Z", (void*) nativeHasContent }, { "nativeDiscardAllTextures", "()V", @@ -1366,6 +1429,10 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeSetHwAccelerated }, { "nativeFindMaxVisibleRect", "(IILandroid/graphics/Rect;)V", (void*) nativeFindMaxVisibleRect }, + { "nativeIsHandleLeft", "(II)Z", + (void*) nativeIsHandleLeft }, + { "nativeIsPointVisible", "(IIII)Z", + (void*) nativeIsPointVisible }, }; int registerWebView(JNIEnv* env) diff --git a/ThirdPartyProject.prop b/ThirdPartyProject.prop deleted file mode 100644 index ae9d227..0000000 --- a/ThirdPartyProject.prop +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2010 Google Inc. All Rights Reserved. -#Fri Sep 10 11:49:27 BST 2010 -currentVersion=55486 -version=84325 -isNative=true -name=webkit -keywords=webkit -onDevice=true -homepage=http\://webkit.org/ -# Currently we track the Chromium 12.0.742 release branch: -# http://trac.webkit.org/browser/branches/chromium/742 -# which is WebKit trunk r84325 plus stability cherry picks. -webkit.chromiumRelease=http\://src.chromium.org/svn/releases/12.0.742.130/DEPS diff --git a/WEBKIT_MERGE_REVISION b/WEBKIT_MERGE_REVISION new file mode 100644 index 0000000..956ae85 --- /dev/null +++ b/WEBKIT_MERGE_REVISION @@ -0,0 +1,5 @@ +Currently we track the Chromium 12.0.742 release branch: +http://trac.webkit.org/browser/branches/chromium/742 +which is WebKit trunk r84325 plus stability cherry picks. + +See also http://src.chromium.org/svn/releases/12.0.742.130/DEPS |