diff options
33 files changed, 381 insertions, 206 deletions
diff --git a/WebCore/bindings/generic/BindingDOMWindow.h b/WebCore/bindings/generic/BindingDOMWindow.h index b46bdf9..f883d11 100644 --- a/WebCore/bindings/generic/BindingDOMWindow.h +++ b/WebCore/bindings/generic/BindingDOMWindow.h @@ -109,7 +109,7 @@ Frame* BindingDOMWindow<Binding>::createWindow(State<Binding>* state, if (created) newFrame->loader()->changeLocation(completedUrl, referrer, false, false, userGesture); else if (!url.isEmpty()) - newFrame->redirectScheduler()->scheduleLocationChange(completedUrl.string(), referrer, false, userGesture); + newFrame->redirectScheduler()->scheduleLocationChange(completedUrl.string(), referrer, false, false, userGesture); } return newFrame; diff --git a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp index 6a53a1f..ff2be37 100644 --- a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp +++ b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp @@ -574,7 +574,7 @@ v8::Handle<v8::Value> V8DOMWindow::openCallback(const v8::Arguments& args) // the outgoingReferrer. We replicate that behavior here. String referrer = enteredFrame->loader()->outgoingReferrer(); - frame->redirectScheduler()->scheduleLocationChange(completedUrl, referrer, false, userGesture); + frame->redirectScheduler()->scheduleLocationChange(completedUrl, referrer, false, false, userGesture); } return toV8(frame->domWindow()); } diff --git a/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp b/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp index 008d1ab..8959189 100644 --- a/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp +++ b/WebCore/bridge/jni/jsc/JavaInstanceJSC.cpp @@ -198,7 +198,9 @@ JSValue JavaInstance::invokeMethod(ExecState* exec, RuntimeMethod* runtimeMethod } } -#ifdef BUILDING_ON_TIGER +// This is a deprecated code path which should not be required on Android. +// Remove this guard once Bug 39476 is fixed. +#if PLATFORM(ANDROID) || defined(BUILDING_ON_TIGER) if (!handled) { jobject obj = m_instance->m_instance; switch (jMethod->JNIReturnType()) { diff --git a/WebCore/dom/EventListener.h b/WebCore/dom/EventListener.h index 249d3eb..d7c950f 100644 --- a/WebCore/dom/EventListener.h +++ b/WebCore/dom/EventListener.h @@ -41,8 +41,7 @@ namespace WebCore { InspectorDOMAgentType, InspectorDOMStorageResourceType, ObjCEventListenerType, - ConditionEventListenerType, - GeolocationEventListenerType }; + ConditionEventListenerType }; virtual ~EventListener() { } virtual bool operator==(const EventListener&) = 0; diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp index 125ee9b..f6b8f52 100644 --- a/WebCore/loader/FrameLoader.cpp +++ b/WebCore/loader/FrameLoader.cpp @@ -59,6 +59,7 @@ #include "FrameLoaderClient.h" #include "FrameTree.h" #include "FrameView.h" +#include "Geolocation.h" #include "HTMLAnchorElement.h" #include "HTMLAppletElement.h" #include "HTMLFormElement.h" @@ -76,6 +77,7 @@ #include "Logging.h" #include "MIMETypeRegistry.h" #include "MainResourceLoader.h" +#include "Navigator.h" #include "Page.h" #include "PageCache.h" #include "PageGroup.h" @@ -605,6 +607,11 @@ void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy, DatabasePolic #endif } + // Stop the Geolocation object, if present. This call is made after the unload + // event has fired, so no new Geolocation activity is possible. + if (m_frame->domWindow()->navigator()->optionalGeolocation()) + m_frame->domWindow()->navigator()->optionalGeolocation()->stop(); + // tell all subframes to stop as well for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) child->loader()->stopLoading(unloadEventPolicy); diff --git a/WebCore/page/Geolocation.cpp b/WebCore/page/Geolocation.cpp index 88e8941..49a4d84 100644 --- a/WebCore/page/Geolocation.cpp +++ b/WebCore/page/Geolocation.cpp @@ -31,10 +31,6 @@ #if ENABLE(GEOLOCATION) #include "Chrome.h" -// ANDROID -#include "DOMWindow.h" -#include "EventNames.h" -// END ANDROID #include "Frame.h" #include "Page.h" #if PLATFORM(ANDROID) @@ -208,10 +204,7 @@ void Geolocation::Watchers::getNotifiersVector(Vector<RefPtr<GeoNotifier> >& cop } Geolocation::Geolocation(Frame* frame) -// ANDROID - : EventListener(GeolocationEventListenerType) - , m_frame(frame) -// END ANDROID + : m_frame(frame) #if !ENABLE(CLIENT_BASED_GEOLOCATION) , m_service(GeolocationService::create(this)) #endif @@ -222,26 +215,23 @@ Geolocation::Geolocation(Frame* frame) return; ASSERT(m_frame->document()); m_frame->document()->setUsingGeolocation(true); - -// ANDROID - if (m_frame->domWindow()) - m_frame->domWindow()->addEventListener(eventNames().unloadEvent, this, false); -// END ANDROID } Geolocation::~Geolocation() { -// ANDROID - if (m_frame && m_frame->domWindow()) - m_frame->domWindow()->removeEventListener(eventNames().unloadEvent, this, false); -// END ANDROID +} + +void Geolocation::stop() +{ + m_oneShots.clear(); + m_watchers.clear(); + stopUpdating(); } void Geolocation::disconnectFrame() { if (m_frame && m_frame->page() && m_allowGeolocation == InProgress) m_frame->page()->chrome()->cancelGeolocationPermissionRequestForFrame(m_frame, this); - stopUpdating(); if (m_frame && m_frame->document()) m_frame->document()->setUsingGeolocation(false); m_frame = 0; @@ -684,26 +674,6 @@ void Geolocation::stopUpdating() } -// ANDROID -bool Geolocation::operator==(const EventListener& listener) -{ - if (listener.type() != GeolocationEventListenerType) - return false; - const Geolocation* geolocation = static_cast<const Geolocation*>(&listener); - return m_frame == geolocation->m_frame; -} - -void Geolocation::handleEvent(ScriptExecutionContext*, Event* event) -{ - ASSERT_UNUSED(event, event->type() == eventNames().unloadEvent); - // Cancel any ongoing requests on page unload. This is required to release - // references to JS callbacks in the page, to allow the frame to be cleaned up - // by WebKit. - m_oneShots.clear(); - m_watchers.clear(); -} -// END ANDROID - } // namespace WebCore #else @@ -720,6 +690,8 @@ Geolocation::~Geolocation() {} void Geolocation::setIsAllowed(bool) {} +void Geolocation::stop() {} + } #endif // ENABLE(GEOLOCATION) diff --git a/WebCore/page/Geolocation.h b/WebCore/page/Geolocation.h index ba4f149..8803703 100644 --- a/WebCore/page/Geolocation.h +++ b/WebCore/page/Geolocation.h @@ -27,9 +27,6 @@ #ifndef Geolocation_h #define Geolocation_h -// ANDROID -#include "EventListener.h" -// END ANDROID #include "GeolocationPositionCache.h" #include "GeolocationService.h" #include "Geoposition.h" @@ -48,9 +45,7 @@ class GeolocationPosition; class GeolocationError; #endif -// ANDROID -class Geolocation : public EventListener -// END ANDROID +class Geolocation : public RefCounted<Geolocation> #if !ENABLE(CLIENT_BASED_GEOLOCATION) && ENABLE(GEOLOCATION) , public GeolocationServiceClient #endif @@ -70,6 +65,8 @@ public: void suspend(); void resume(); + void stop(); + void setIsAllowed(bool); Frame* frame() const { return m_frame; } @@ -154,12 +151,6 @@ private: PassRefPtr<GeoNotifier> startRequest(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); -// ANDROID - // EventListener - virtual bool operator==(const EventListener&); - virtual void handleEvent(ScriptExecutionContext*, Event*); -// END ANDROID - void fatalErrorOccurred(GeoNotifier*); void requestTimedOut(GeoNotifier*); void requestUsesCachedPosition(GeoNotifier*); diff --git a/WebCore/platform/android/FileChooserAndroid.cpp b/WebCore/platform/android/FileChooserAndroid.cpp index 1f8200f..f2ad3b9 100644 --- a/WebCore/platform/android/FileChooserAndroid.cpp +++ b/WebCore/platform/android/FileChooserAndroid.cpp @@ -25,22 +25,20 @@ #include "config.h" #include "FileChooser.h" +#include "FileSystem.h" #include "Font.h" +#include "LocalizedStrings.h" +#include "StringTruncator.h" namespace WebCore { String FileChooser::basenameForWidth(const Font& font, int width) const { if (!m_filenames.size()) - return String(); - // FIXME: This could be a lot faster, but assuming the data will not - // often be much longer than the provided width, this may be fast enough. - // If this does not need to be threadsafe, we can use crossThreadString(). - // See http://trac.webkit.org/changeset/49160. - String output = m_filenames[0].threadsafeCopy(); - while (font.width(TextRun(output.impl())) > width && output.length() > 4) - output = output.replace(0, 4, String("...")); - return output; + return fileButtonNoFileSelectedLabel(); + + String output = pathGetFileName(m_filenames[0]); + return StringTruncator::centerTruncate(output, static_cast<float>(width), font, false); } } // namespace WebCore diff --git a/WebCore/platform/android/FileSystemAndroid.cpp b/WebCore/platform/android/FileSystemAndroid.cpp index 3d841d7..cf9830e 100644 --- a/WebCore/platform/android/FileSystemAndroid.cpp +++ b/WebCore/platform/android/FileSystemAndroid.cpp @@ -28,6 +28,7 @@ #include "config.h" #include "FileSystem.h" +#include "PlatformBridge.h" #include "StringBuilder.h" #include "cutils/log.h" #include <dirent.h> @@ -106,4 +107,14 @@ Vector<String> listDirectory(const String& path, const String& filter) return entries; } +String pathGetFileName(const String& path) +{ + // If the path is a content:// URI then ask Java to resolve it for us. + if (path.startsWith("content://")) + return PlatformBridge::resolveFileNameForContentUri(path); + else + return path.substring(path.reverseFind('/') + 1); +} + + } // namespace WebCore diff --git a/WebCore/platform/android/LocalizedStringsAndroid.cpp b/WebCore/platform/android/LocalizedStringsAndroid.cpp index e0db88d..5ca7fa2 100644 --- a/WebCore/platform/android/LocalizedStringsAndroid.cpp +++ b/WebCore/platform/android/LocalizedStringsAndroid.cpp @@ -48,8 +48,8 @@ String fileButtonChooseFileLabel() String fileButtonNoFileSelectedLabel() { - notImplemented(); - return String(); + return *(PlatformBridge::globalLocalizedName( + PlatformBridge::FileUploadNoFileChosenLabel)); } String contextMenuItemTagInspectElement() diff --git a/WebCore/platform/android/PlatformBridge.h b/WebCore/platform/android/PlatformBridge.h index 43313a5..33f8697 100644 --- a/WebCore/platform/android/PlatformBridge.h +++ b/WebCore/platform/android/PlatformBridge.h @@ -119,7 +119,8 @@ public: DrawableDir, FileUploadLabel, ResetLabel, - SubmitLabel + SubmitLabel, + FileUploadNoFileChosenLabel }; static String* globalLocalizedName(rawResId resId); @@ -135,6 +136,9 @@ public: // ANDROID // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082 static bool isWebViewPaused(const FrameView*); + + static bool canScroll(const FrameView*); + static String resolveFileNameForContentUri(const String&); }; } diff --git a/WebCore/platform/android/ScrollViewAndroid.cpp b/WebCore/platform/android/ScrollViewAndroid.cpp index f9e4285..7efc8c1 100644 --- a/WebCore/platform/android/ScrollViewAndroid.cpp +++ b/WebCore/platform/android/ScrollViewAndroid.cpp @@ -30,8 +30,8 @@ #include "FloatRect.h" #include "FrameView.h" #include "IntRect.h" +#include "PlatformBridge.h" #include "SkRegion.h" -#include "WebCoreFrameBridge.h" #include "WebCoreViewBridge.h" #include "WebViewCore.h" @@ -70,6 +70,8 @@ void ScrollView::platformSetScrollPosition(const WebCore::IntPoint& pt) { if (parent()) // don't attempt to scroll subframes; they're fully visible return; + if (isFrameView() && !PlatformBridge::canScroll(static_cast<FrameView*>(this))) + return; android::WebViewCore::getWebViewCore(this)->scrollTo(pt.x(), pt.y()); } diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 0d22719..c3df943 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -229,30 +229,39 @@ void GraphicsLayerAndroid::updateFixedPosition() // If we are a fixed position layer, just set it if (view->isPositioned() && view->style()->position() == FixedPosition) { + // We need to get the passed CSS properties for the element SkLength left, top, right, bottom; left = convertLength(view->style()->left()); top = convertLength(view->style()->top()); right = convertLength(view->style()->right()); bottom = convertLength(view->style()->bottom()); - // We need to pass the size of the element to compute the final fixed - // position -- we can't use the layer's size as it could possibly differs. - // We also have to use the visible overflow and not just the size, - // as some child elements could be overflowing. - int w = view->rightVisibleOverflow() - view->leftVisibleOverflow(); - int h = view->bottomVisibleOverflow() - view->topVisibleOverflow(); + // We also need to get the margin... SkLength marginLeft, marginTop, marginRight, marginBottom; marginLeft = convertLength(view->style()->marginLeft()); marginTop = convertLength(view->style()->marginTop()); marginRight = convertLength(view->style()->marginRight()); marginBottom = convertLength(view->style()->marginBottom()); + // The layer can be bigger than the element we want to draw; + // not only that, the layout rect of the element might also be + // different from the visible rect of that element (i.e. the element + // has a CSS shadow property -- the shadow is "outside" the element). + // We thus need to: + // 1/ get the size of the element (w,h), using the layoutOverflow rect + // 2/ pass the current offset of the painting relative to the layer + int w = view->rightLayoutOverflow() - view->leftLayoutOverflow(); + int h = view->bottomLayoutOverflow() - view->topLayoutOverflow(); + int paintingOffsetX = - offsetFromRenderer().width(); + int paintingOffsetY = - offsetFromRenderer().height(); + + SkRect viewRect; + viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h); + m_contentLayer->setFixedPosition(left, top, right, bottom, marginLeft, marginTop, marginRight, marginBottom, - offsetFromRenderer().width(), - offsetFromRenderer().height(), - w, h); + viewRect); } } @@ -283,6 +292,7 @@ void GraphicsLayerAndroid::setSize(const FloatSize& size) MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height()); GraphicsLayer::setSize(size); m_contentLayer->setSize(size.width(), size.height()); + updateFixedPosition(); askForSync(); } } diff --git a/WebCore/platform/graphics/android/ImageBufferAndroid.cpp b/WebCore/platform/graphics/android/ImageBufferAndroid.cpp index 6efccfe..92c585f 100644 --- a/WebCore/platform/graphics/android/ImageBufferAndroid.cpp +++ b/WebCore/platform/graphics/android/ImageBufferAndroid.cpp @@ -24,11 +24,11 @@ */ #include "config.h" -#include "BitmapImage.h" #include "ImageBuffer.h" -#include "ImageData.h" -#include "NotImplemented.h" +#include "Base64.h" +#include "BitmapImage.h" +#include "ImageData.h" #include "android_graphics.h" #include "GraphicsContext.h" #include "PlatformGraphicsContext.h" @@ -36,6 +36,8 @@ #include "SkCanvas.h" #include "SkColorPriv.h" #include "SkDevice.h" +#include "SkImageEncoder.h" +#include "SkStream.h" #include "SkUnPreMultiply.h" using namespace std; @@ -208,10 +210,22 @@ void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sou String ImageBuffer::toDataURL(const String&) const -{ - // leaving this unimplemented, until I understand what its for (and what it - // really is). - return "data:,"; // I think this means we couldn't make the data url +{ + // Encode the image into a vector. + SkDynamicMemoryWStream pngStream; + const SkBitmap& dst = android_gc2canvas(context())->getDevice()->accessBitmap(true); + SkImageEncoder::EncodeStream(&pngStream, dst, SkImageEncoder::kPNG_Type, 100); + + // Convert it into base64. + Vector<char> pngEncodedData; + pngEncodedData.append(pngStream.getStream(), pngStream.getOffset()); + Vector<char> base64EncodedData; + base64Encode(pngEncodedData, base64EncodedData); + // Append with a \0 so that it's a valid string. + base64EncodedData.append('\0'); + + // And the resulting string. + return String::format("data:image/png;base64,%s", base64EncodedData.data()); } } diff --git a/WebCore/platform/graphics/android/ImageSourceAndroid.cpp b/WebCore/platform/graphics/android/ImageSourceAndroid.cpp index 914a9d6..c0ef611 100644 --- a/WebCore/platform/graphics/android/ImageSourceAndroid.cpp +++ b/WebCore/platform/graphics/android/ImageSourceAndroid.cpp @@ -303,7 +303,7 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived) } PrivateAndroidImageSourceRec* decoder = m_decoder.m_image; - if (allDataReceived && !decoder->fAllDataReceived) { + if (allDataReceived && decoder && !decoder->fAllDataReceived) { decoder->fAllDataReceived = true; SkBitmap* bm = &decoder->bitmap(); diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index 2f10d33..5aaa243 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -87,9 +87,7 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer), m_fixedMarginTop = layer.m_fixedMarginTop; m_fixedMarginRight = layer.m_fixedMarginRight; m_fixedMarginBottom = layer.m_fixedMarginBottom; - m_fixedOffset = layer.m_fixedOffset; - m_fixedWidth = layer.m_fixedWidth; - m_fixedHeight = layer.m_fixedHeight; + m_fixedRect = layer.m_fixedRect; m_recordingPicture = layer.m_recordingPicture; SkSafeRef(m_recordingPicture); @@ -256,20 +254,6 @@ const LayerAndroid* LayerAndroid::find(int x, int y) const /////////////////////////////////////////////////////////////////////////////// -// The Layer bounds and the renderview bounds are not always indentical. -// We need to compute the intersection to correctly compute the -// positiong... -static SkRect computeLayerRect(LayerAndroid* layer) { - SkRect layerRect, viewRect; - SkScalar fX, fY; - fX = layer->getOffset().fX; - fY = layer->getOffset().fY; - layerRect.set(0, 0, layer->getSize().width(), layer->getSize().height()); - viewRect.set(-fX, -fY, -fX + layer->getFixedWidth(), -fY + layer->getFixedHeight()); - layerRect.intersect(viewRect); - return layerRect; -} - void LayerAndroid::updateFixedLayersPositions(const SkRect& viewport) { if (m_isFixed) { @@ -280,23 +264,21 @@ void LayerAndroid::updateFixedLayersPositions(const SkRect& viewport) float x = dx; float y = dy; - SkRect layerRect = computeLayerRect(this); - // Not defined corresponds to 'auto'; - // so if right is auto, and left is auto, the w3c says we should set - // left to zero (in left-to-right layout). So basically, if right is not - // defined, we always apply auto. - if (m_fixedRight.defined()) - x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - layerRect.width(); + // If both left and right are auto, the w3c says we should set left + // to zero (in left-to-right layout). So we use left if it's defined + // or if right isn't defined. + if (m_fixedLeft.defined() || !m_fixedRight.defined()) + x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft; else - x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - layerRect.fLeft; + x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight; // Following the same reason as above, if bottom isn't defined, we apply // top regardless of it being defined or not. - if (m_fixedBottom.defined()) - y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - layerRect.fTop - layerRect.height(); + if (m_fixedTop.defined() || !m_fixedBottom.defined()) + y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop; else - y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - layerRect.fTop; + y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom; this->setPosition(x, y); } @@ -375,10 +357,9 @@ void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) { canvas->drawLine(w, 0, 0, 0, paint); if (m_isFixed) { - SkRect layerRect = computeLayerRect(this); SkPaint paint; - paint.setARGB(128, 0, 0, 255); - canvas->drawRect(layerRect, paint); + paint.setARGB(80, 255, 0, 0); + canvas->drawRect(m_fixedRect, paint); } #endif } @@ -513,6 +494,13 @@ void writeSize(FILE* file, int indentLevel, const char* str, SkSize size) fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height()); } +void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect) +{ + writeIndent(file, indentLevel); + fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n", + str, rect.fLeft, rect.fTop, rect.width(), rect.height()); +} + void writeLength(FILE* file, int indentLevel, const char* str, SkLength length) { if (!length.defined()) return; @@ -549,9 +537,7 @@ void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop); writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight); writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom); - writePoint(file, indentLevel + 1, "fixedOffset", m_fixedOffset); - writeIntVal(file, indentLevel + 1, "fixedWidth", m_fixedWidth); - writeIntVal(file, indentLevel + 1, "fixedHeight", m_fixedHeight); + writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect); } if (m_recordingPicture) { diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h index 2b106d1..b6b6f70 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.h +++ b/WebCore/platform/graphics/android/LayerAndroid.h @@ -104,10 +104,7 @@ public: SkLength marginTop, // CSS margin-top property SkLength marginRight, // CSS margin-right property SkLength marginBottom, // CSS margin-bottom property - int offsetX, // X Offset from the renderer - int offsetY, // Y Offset from the renderer - int width, // visible overflow width - int height) { // visible overflow height + SkRect viewRect) { // view rect, can be smaller than the layer's m_fixedLeft = left; m_fixedTop = top; m_fixedRight = right; @@ -116,9 +113,7 @@ public: m_fixedMarginTop = marginTop; m_fixedMarginRight = marginRight; m_fixedMarginBottom = marginBottom; - m_fixedOffset.set(offsetX, offsetY); - m_fixedWidth = width; - m_fixedHeight = height; + m_fixedRect = viewRect; m_isFixed = true; setInheritFromRootTransform(true); } @@ -171,9 +166,6 @@ public: void setExtra(DrawExtra* extra); // does not assign ownership int uniqueId() const { return m_uniqueId; } bool isFixed() { return m_isFixed; } - const SkPoint& getOffset() const { return m_fixedOffset; } - int getFixedWidth() { return m_fixedWidth; } - int getFixedHeight() { return m_fixedHeight; } /** This sets a content image -- calling it means we will use the image directly when drawing the layer instead of using @@ -208,9 +200,7 @@ private: SkLength m_fixedMarginTop; SkLength m_fixedMarginRight; SkLength m_fixedMarginBottom; - SkPoint m_fixedOffset; - int m_fixedWidth; - int m_fixedHeight; + SkRect m_fixedRect; SkPoint m_translation; SkPoint m_scale; diff --git a/WebCore/platform/posix/FileSystemPOSIX.cpp b/WebCore/platform/posix/FileSystemPOSIX.cpp index ac8c7fa..b7fcd71 100644 --- a/WebCore/platform/posix/FileSystemPOSIX.cpp +++ b/WebCore/platform/posix/FileSystemPOSIX.cpp @@ -213,10 +213,12 @@ bool makeAllDirectories(const String& path) return true; } +#if !PLATFORM(ANDROID) String pathGetFileName(const String& path) { return path.substring(path.reverseFind('/') + 1); } +#endif String directoryName(const String& path) { diff --git a/WebCore/plugins/PluginView.cpp b/WebCore/plugins/PluginView.cpp index fe24109..73ac220 100644 --- a/WebCore/plugins/PluginView.cpp +++ b/WebCore/plugins/PluginView.cpp @@ -69,8 +69,6 @@ #include "TouchEvent.h" #endif -// ANDROID -// TODO: Upstream to webkit.org #if USE(JSC) #include "JSDOMBinding.h" #include "JSDOMWindow.h" @@ -233,7 +231,6 @@ bool PluginView::startOrAddToUnstartedList() return start(); } - bool PluginView::start() { if (m_isStarted) @@ -249,7 +246,7 @@ bool PluginView::start() NPError npErr; { PluginView::setCurrentPluginView(this); -#if USE(JSC) +#if USE(JSC) JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); #endif setCallingPlugin(true); @@ -362,6 +359,7 @@ void PluginView::stop() ASSERT(m_streams.isEmpty()); m_isStarted = false; + #if USE(JSC) JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); #endif @@ -447,22 +445,6 @@ static char* createUTF8String(const String& str) return result; } -#if USE(JSC) -static bool getString(ScriptController* proxy, JSValue result, String& string) -{ - if (!proxy || !result || result.isUndefined()) - return false; - JSLock lock(JSC::SilenceAssertionsOnly); - - ExecState* exec = proxy->globalObject(pluginWorld())->globalExec(); - UString ustring = result.toString(exec); - exec->clearException(); - - string = ustringToString(ustring); - return true; -} -#endif - void PluginView::performRequest(PluginRequest* request) { if (!m_isStarted) @@ -495,7 +477,7 @@ void PluginView::performRequest(PluginRequest* request) // FIXME: <rdar://problem/4807469> This should be sent when the document has finished loading if (request->sendNotification()) { PluginView::setCurrentPluginView(this); -#if USE(JSC) +#if USE(JSC) JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); #endif setCallingPlugin(true); @@ -510,7 +492,7 @@ void PluginView::performRequest(PluginRequest* request) // Targeted JavaScript requests are only allowed on the frame that contains the JavaScript plugin // and this has been made sure in ::load. ASSERT(targetFrameName.isEmpty() || m_parentFrame->tree()->find(targetFrameName) == m_parentFrame); - + // Executing a script can cause the plugin view to be destroyed, so we keep a reference to the parent frame. RefPtr<Frame> parentFrame = m_parentFrame; ScriptValue result = m_parentFrame->script()->executeScript(jsString, request->shouldAllowPopups()); @@ -518,19 +500,14 @@ void PluginView::performRequest(PluginRequest* request) if (targetFrameName.isNull()) { String resultString; - CString cstr; #if USE(JSC) - if (getString(parentFrame->script(), result.jsValue(), resultString)) - cstr = resultString.utf8(); + ScriptState* scriptState = parentFrame->script()->globalObject(pluginWorld())->globalExec(); #elif USE(V8) - // #if PLATFORM(ANDROID) - // TODO. When upstreaming this, we could re-visit whether the JSC getString function in this file - // could be removed, and this code re-factored to call ScriptValue::getString(ScriptState* scriptState, String& result) - // in both cases, thus getting rid of the #ifs - // #endif - if (result.getString(resultString)) - cstr = resultString.utf8(); + ScriptState* scriptState = 0; // Not used with V8 #endif + CString cstr; + if (result.getString(scriptState, resultString)) + cstr = resultString.utf8(); RefPtr<PluginStream> stream = PluginStream::create(this, m_parentFrame.get(), request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_plugin->quirks()); m_streams.add(stream); @@ -787,7 +764,6 @@ void PluginView::setJavaScriptPaused(bool paused) m_requestTimer.startOneShot(0); } - #if USE(JSC) PassRefPtr<JSC::Bindings::Instance> PluginView::bindingInstance() { diff --git a/WebCore/plugins/PluginView.h b/WebCore/plugins/PluginView.h index 88136e3..b685bbf 100644 --- a/WebCore/plugins/PluginView.h +++ b/WebCore/plugins/PluginView.h @@ -1,4 +1,3 @@ - /* * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2008 Collabora Ltd. All rights reserved. @@ -140,8 +139,6 @@ namespace WebCore { #if USE(JSC) PassRefPtr<JSC::Bindings::Instance> bindingInstance(); -#elif USE(V8) - NPObject* getNPObject(); #endif PluginStatus status() const { return m_status; } @@ -175,6 +172,9 @@ namespace WebCore { void (*timerFunc)(NPP, uint32_t timerID)); void unscheduleTimer(NPP, uint32_t timerID); #endif +#if USE(V8) + NPObject* getNPObject(); +#endif virtual void invalidateRect(const IntRect&); diff --git a/WebCore/rendering/RenderIFrame.cpp b/WebCore/rendering/RenderIFrame.cpp index 90cac14..146e028 100644 --- a/WebCore/rendering/RenderIFrame.cpp +++ b/WebCore/rendering/RenderIFrame.cpp @@ -58,9 +58,7 @@ void RenderIFrame::calcHeight() updateWidgetPosition(); // Layout to get the content height - do { - view->layout(); - } while (view->layoutPending() || root->needsLayout()); + view->layout(); int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom(); setHeight(max(width(), view->contentsHeight() + extraHeight)); @@ -110,9 +108,7 @@ void RenderIFrame::calcWidth() updateWidgetPosition(); // Layout to get the content width - do { - view->layout(); - } while (view->layoutPending() || root->needsLayout()); + view->layout(); setWidth(max(width(), view->contentsWidth() + extraWidth)); @@ -208,9 +204,7 @@ void RenderIFrame::layout() } // Layout the view. - do { - view->layout(); - } while (view->layoutPending() || root->needsLayout()); + view->layout(); int contentHeight = view->contentsHeight(); int contentWidth = view->contentsWidth(); diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp index b59689d..ead81e0 100644 --- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp @@ -57,11 +57,16 @@ static unsigned long long tryToReclaimDatabaseQuota(SecurityOrigin* originNeedin #if USE(ACCELERATED_COMPOSITING) -void ChromeClientAndroid::syncTimerFired(Timer<ChromeClientAndroid>* client) +void ChromeClientAndroid::layersSync() { if (!m_rootGraphicsLayer) return; + if (!m_needsLayerSync) + return; + + m_needsLayerSync = false; + if (m_webFrame) { FrameView* frameView = m_webFrame->page()->mainFrame()->view(); if (frameView && frameView->syncCompositingStateRecursive()) { @@ -77,8 +82,7 @@ void ChromeClientAndroid::syncTimerFired(Timer<ChromeClientAndroid>* client) void ChromeClientAndroid::scheduleCompositingLayerSync() { - if (!m_syncTimer.isActive()) - m_syncTimer.startOneShot(0); + m_needsLayerSync = true; } void ChromeClientAndroid::setNeedsOneShotDrawingSynchronization() diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h index 902d84c..28f2546 100644 --- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h @@ -46,8 +46,7 @@ namespace android { ChromeClientAndroid() : m_webFrame(0), m_geolocationPermissions(0) #if USE(ACCELERATED_COMPOSITING) , m_rootGraphicsLayer(0) - , m_askToDrawAgain(false) - , m_syncTimer(this, &ChromeClientAndroid::syncTimerFired) + , m_needsLayerSync(false) #endif , m_triedToReclaimDBQuota(false) { } @@ -170,7 +169,7 @@ namespace android { virtual void attachRootGraphicsLayer(WebCore::Frame*, WebCore::GraphicsLayer* g); virtual void setNeedsOneShotDrawingSynchronization(); virtual void scheduleCompositingLayerSync(); - void syncTimerFired(Timer<ChromeClientAndroid>*); + void layersSync(); #endif private: @@ -179,8 +178,7 @@ namespace android { OwnPtr<GeolocationPermissions> m_geolocationPermissions; #if USE(ACCELERATED_COMPOSITING) WebCore::GraphicsLayer* m_rootGraphicsLayer; - bool m_askToDrawAgain; - Timer<ChromeClientAndroid> m_syncTimer; + bool m_needsLayerSync; #endif WTF::ThreadCondition m_quotaThreadCondition; WTF::Mutex m_quotaThreadLock; diff --git a/WebKit/android/WebCoreSupport/FileSystemClient.h b/WebKit/android/WebCoreSupport/FileSystemClient.h new file mode 100644 index 0000000..8847bda --- /dev/null +++ b/WebKit/android/WebCoreSupport/FileSystemClient.h @@ -0,0 +1,41 @@ +/* + * Copyright 2010, 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 FILESYSTEM_CLIENT_H +#define FILESYSTEM_CLIENT_H + +#include "PlatformString.h" + +using namespace WebCore; + +namespace android { + +class FileSystemClient { +public: + virtual ~FileSystemClient() { } + virtual String resolveFileNameForContentUri(const String&) = 0; +}; +} +#endif diff --git a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp index 697f7b9..79c64fd 100644 --- a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp @@ -395,7 +395,9 @@ void FrameLoaderClientAndroid::dispatchDidFinishLoad() { void FrameLoaderClientAndroid::dispatchDidFirstLayout() { ASSERT(m_frame); - m_frame->document()->setExtraLayoutDelay(EXTRA_LAYOUT_DELAY); + // set EXTRA_LAYOUT_DELAY if the loader is not completed yet + if (!m_frame->loader()->isComplete()) + m_frame->document()->setExtraLayoutDelay(EXTRA_LAYOUT_DELAY); // we need to do this here instead of dispatchDidFirstVisuallyNonEmptyLayout // so that about:blank will update the screen. if (!m_frame->tree()->parent()) { diff --git a/WebKit/android/WebCoreSupport/PlatformBridge.cpp b/WebKit/android/WebCoreSupport/PlatformBridge.cpp index 05aa42b..c64bb9d 100644 --- a/WebKit/android/WebCoreSupport/PlatformBridge.cpp +++ b/WebKit/android/WebCoreSupport/PlatformBridge.cpp @@ -27,9 +27,12 @@ #include <PlatformBridge.h> #include "CookieClient.h" +#include "FileSystemClient.h" +#include "FrameView.h" #include "JavaSharedClient.h" #include "KeyGeneratorClient.h" #include "PluginView.h" +#include "WebCoreFrameBridge.h" #include "WebViewCore.h" #include "npruntime.h" #include <wtf/android/AndroidThreading.h> @@ -135,11 +138,28 @@ bool PlatformBridge::isWebViewPaused(const WebCore::FrameView* frameView) return webViewCore->isPaused(); } +bool PlatformBridge::canScroll(const WebCore::FrameView* frameView) +{ + // We want to ignore requests to scroll that were not initiated by the + // user. An example of this is when text is inserted into a + // textfield/area, which results in a scroll. We ignore this because + // we know how to do this ourselves in the UI thread. + // An example of it being initiated by the user is if the user clicks + // an anchor element which simply scrolls the page. + return android::WebFrame::getWebFrame(frameView->frame())->userInitiatedClick(); +} + bool PlatformBridge::popupsAllowed(NPP) { return false; } +String PlatformBridge::resolveFileNameForContentUri(const String& contentUri) +{ + FileSystemClient* client = JavaSharedClient::GetFileSystemClient(); + return client->resolveFileNameForContentUri(contentUri); +} + } // namespace WebCore diff --git a/WebKit/android/jni/JavaBridge.cpp b/WebKit/android/jni/JavaBridge.cpp index 0e65e1c..2d95f87 100644 --- a/WebKit/android/jni/JavaBridge.cpp +++ b/WebKit/android/jni/JavaBridge.cpp @@ -31,6 +31,7 @@ #include "Cache.h" #include "Connection.h" #include "CookieClient.h" +#include "FileSystemClient.h" #include "JavaSharedClient.h" #include "KeyGeneratorClient.h" #include "KURL.h" @@ -62,7 +63,7 @@ static jfieldID gJavaBridge_ObjectID; // ---------------------------------------------------------------------------- -class JavaBridge : public TimerClient, public CookieClient, public PluginClient, public KeyGeneratorClient +class JavaBridge : public TimerClient, public CookieClient, public PluginClient, public KeyGeneratorClient, public FileSystemClient { public: JavaBridge(JNIEnv* env, jobject obj); @@ -84,6 +85,7 @@ public: virtual WTF::Vector<String> getSupportedKeyStrengthList(); virtual WebCore::String getSignedPublicKeyAndChallengeString(unsigned index, const WebCore::String& challenge, const WebCore::KURL& url); + virtual WebCore::String resolveFileNameForContentUri(const WebCore::String& uri); //////////////////////////////////////////// @@ -120,6 +122,7 @@ private: jmethodID mSignalFuncPtrQueue; jmethodID mGetKeyStrengthList; jmethodID mGetSignedPublicKey; + jmethodID mResolveFileNameForContentUri; }; static void (*sSharedTimerFiredCallback)(); @@ -139,6 +142,7 @@ JavaBridge::JavaBridge(JNIEnv* env, jobject obj) mSignalFuncPtrQueue = env->GetMethodID(clazz, "signalServiceFuncPtrQueue", "()V"); mGetKeyStrengthList = env->GetMethodID(clazz, "getKeyStrengthList", "()[Ljava/lang/String;"); mGetSignedPublicKey = env->GetMethodID(clazz, "getSignedPublicKey", "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); + mResolveFileNameForContentUri = env->GetMethodID(clazz, "resolveFileNameForContentUri", "(Ljava/lang/String;)Ljava/lang/String;"); LOG_ASSERT(mSetSharedTimer, "Could not find method setSharedTimer"); LOG_ASSERT(mStopSharedTimer, "Could not find method stopSharedTimer"); @@ -154,6 +158,7 @@ JavaBridge::JavaBridge(JNIEnv* env, jobject obj) JavaSharedClient::SetCookieClient(this); JavaSharedClient::SetPluginClient(this); JavaSharedClient::SetKeyGeneratorClient(this); + JavaSharedClient::SetFileSystemClient(this); } JavaBridge::~JavaBridge() @@ -168,6 +173,7 @@ JavaBridge::~JavaBridge() JavaSharedClient::SetCookieClient(NULL); JavaSharedClient::SetPluginClient(NULL); JavaSharedClient::SetKeyGeneratorClient(NULL); + JavaSharedClient::SetFileSystemClient(NULL); } void @@ -308,6 +314,17 @@ WebCore::String JavaBridge::getSignedPublicKeyAndChallengeString(unsigned index, return ret; } +WebCore::String JavaBridge::resolveFileNameForContentUri(const WebCore::String& uri) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jstring jUri = env->NewString(uri.characters(), uri.length()); + AutoJObject obj = getRealObject(env, mJavaObject); + jstring path = static_cast<jstring>(env->CallObjectMethod(obj.get(), mResolveFileNameForContentUri, jUri)); + WebCore::String ret = to_string(env, path); + env->DeleteLocalRef(jUri); + env->DeleteLocalRef(path); + return ret; +} + // ---------------------------------------------------------------------------- void JavaBridge::Constructor(JNIEnv* env, jobject obj) diff --git a/WebKit/android/jni/JavaSharedClient.cpp b/WebKit/android/jni/JavaSharedClient.cpp index ce46570..e884c99 100644 --- a/WebKit/android/jni/JavaSharedClient.cpp +++ b/WebKit/android/jni/JavaSharedClient.cpp @@ -24,6 +24,7 @@ */ #include "config.h" +#include "FileSystemClient.h" #include "JavaSharedClient.h" #include "TimerClient.h" #include "SkDeque.h" @@ -50,6 +51,11 @@ namespace android { return gKeyGeneratorClient; } + FileSystemClient* JavaSharedClient::GetFileSystemClient() + { + return gFileSystemClient; + } + void JavaSharedClient::SetTimerClient(TimerClient* client) { gTimerClient = client; @@ -70,10 +76,16 @@ namespace android { gKeyGeneratorClient = client; } + void JavaSharedClient::SetFileSystemClient(FileSystemClient* client) + { + gFileSystemClient = client; + } + TimerClient* JavaSharedClient::gTimerClient = NULL; CookieClient* JavaSharedClient::gCookieClient = NULL; PluginClient* JavaSharedClient::gPluginClient = NULL; KeyGeneratorClient* JavaSharedClient::gKeyGeneratorClient = NULL; + FileSystemClient* JavaSharedClient::gFileSystemClient = NULL; /////////////////////////////////////////////////////////////////////////// diff --git a/WebKit/android/jni/JavaSharedClient.h b/WebKit/android/jni/JavaSharedClient.h index d33df67..9a09280 100644 --- a/WebKit/android/jni/JavaSharedClient.h +++ b/WebKit/android/jni/JavaSharedClient.h @@ -32,6 +32,7 @@ namespace android { class CookieClient; class PluginClient; class KeyGeneratorClient; + class FileSystemClient; class JavaSharedClient { @@ -40,11 +41,13 @@ namespace android { static CookieClient* GetCookieClient(); static PluginClient* GetPluginClient(); static KeyGeneratorClient* GetKeyGeneratorClient(); + static FileSystemClient* GetFileSystemClient(); static void SetTimerClient(TimerClient* client); static void SetCookieClient(CookieClient* client); static void SetPluginClient(PluginClient* client); static void SetKeyGeneratorClient(KeyGeneratorClient* client); + static void SetFileSystemClient(FileSystemClient* client); // can be called from any thread, to be executed in webkit thread static void EnqueueFunctionPtr(void (*proc)(void*), void* payload); @@ -56,6 +59,7 @@ namespace android { static CookieClient* gCookieClient; static PluginClient* gPluginClient; static KeyGeneratorClient* gKeyGeneratorClient; + static FileSystemClient* gFileSystemClient; }; } #endif diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp index 9ecb121..de172cd 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -116,6 +116,7 @@ using namespace JSC::Bindings; static String* gUploadFileLabel; static String* gResetLabel; static String* gSubmitLabel; +static String* gNoFileChosenLabel; String* WebCore::PlatformBridge::globalLocalizedName( WebCore::PlatformBridge::rawResId resId) @@ -127,6 +128,9 @@ String* WebCore::PlatformBridge::globalLocalizedName( return gResetLabel; case WebCore::PlatformBridge::SubmitLabel: return gSubmitLabel; + case WebCore::PlatformBridge::FileUploadNoFileChosenLabel: + return gNoFileChosenLabel; + default: return 0; } @@ -148,6 +152,9 @@ void initGlobalLocalizedName(WebCore::PlatformBridge::rawResId resId, case WebCore::PlatformBridge::SubmitLabel: pointer = &gSubmitLabel; break; + case WebCore::PlatformBridge::FileUploadNoFileChosenLabel: + pointer = &gNoFileChosenLabel; + break; default: return; } @@ -320,19 +327,6 @@ static jobject createJavaMapFromHTTPHeaders(JNIEnv* env, const WebCore::HTTPHead return hashMap; } -// In WebViewCore.java, we artificially append the filename to the URI so that -// webkit treats the actual display name of the file as the filename, rather -// than the last segment of the URI (which will simply be a number). When we -// pass the URI up to BrowserFrame, we no longer need the appended name (in fact -// it causes problems), so remove it here. -// FIXME: If we rewrite pathGetFileName (the current version is in -// FileSystemPOSIX), we can get the filename that way rather than appending it. -static jstring uriFromUriFileName(JNIEnv* env, const WebCore::String& name) -{ - const WebCore::String fileName = name.left(name.reverseFind('/')); - return env->NewString(fileName.characters(), fileName.length()); -} - // This class stores the URI and the size of each file for upload. The URI is // stored so we do not have to create it again. The size is stored so we can // compare the actual size of the file with the stated size. If the actual size @@ -341,7 +335,7 @@ static jstring uriFromUriFileName(JNIEnv* env, const WebCore::String& name) class FileInfo { public: FileInfo(JNIEnv* env, const WebCore::String& name) { - m_uri = uriFromUriFileName(env, name); + m_uri = env->NewString(name.characters(), name.length()); checkException(env); m_size = 0; m_env = env; @@ -940,7 +934,7 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss WebCore::RenderSkinAndroid::Init(am, directory); } for (int i = WebCore::PlatformBridge::FileUploadLabel; - i <= WebCore::PlatformBridge::SubmitLabel; i++) + i <= WebCore::PlatformBridge::FileUploadNoFileChosenLabel; i++) initGlobalLocalizedName( static_cast<WebCore::PlatformBridge::rawResId>(i), webFrame); } diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index 50611c7..45356f8 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -308,7 +308,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_javaGlue->m_scrollBy = GetJMethod(env, clazz, "contentScrollBy", "(IIZ)V"); m_javaGlue->m_contentDraw = GetJMethod(env, clazz, "contentDraw", "()V"); m_javaGlue->m_requestListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[I[I)V"); - m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "()Ljava/lang/String;"); + m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "(Ljava/lang/String;)Ljava/lang/String;"); m_javaGlue->m_requestSingleListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[II)V"); m_javaGlue->m_jsAlert = GetJMethod(env, clazz, "jsAlert", "(Ljava/lang/String;Ljava/lang/String;)V"); m_javaGlue->m_jsConfirm = GetJMethod(env, clazz, "jsConfirm", "(Ljava/lang/String;Ljava/lang/String;)Z"); @@ -884,6 +884,12 @@ bool WebViewCore::recordContent(SkRegion* region, SkIPoint* point) region->getBounds().fTop, region->getBounds().fRight, region->getBounds().fBottom); DBG_SET_LOG("end"); + +#if USE(ACCELERATED_COMPOSITING) + // We update the layers + ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client()); + chromeC->layersSync(); +#endif return true; } @@ -1969,15 +1975,24 @@ void WebViewCore::openFileChooser(PassRefPtr<WebCore::FileChooser> chooser) { if (!chooser) return; JNIEnv* env = JSC::Bindings::getJNIEnv(); + + WebCore::String acceptType = chooser->acceptTypes(); + jstring jAcceptType = env->NewString(const_cast<unsigned short*>(acceptType.characters()), acceptType.length()); jstring jName = (jstring) env->CallObjectMethod( - m_javaGlue->object(env).get(), m_javaGlue->m_openFileChooser); + m_javaGlue->object(env).get(), m_javaGlue->m_openFileChooser, jAcceptType); checkException(env); - const UChar* string = (const UChar*) env->GetStringChars(jName, NULL); + env->DeleteLocalRef(jAcceptType); + + const UChar* string = static_cast<const UChar*>(env->GetStringChars(jName, NULL)); + if (!string) return; + WebCore::String webcoreString = to_string(env, jName); env->ReleaseStringChars(jName, string); - chooser->chooseFile(webcoreString); + + if (webcoreString.length()) + chooser->chooseFile(webcoreString); } void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, size_t count, const int enabled[], size_t enabledCount, diff --git a/WebKit/android/nav/SelectText.cpp b/WebKit/android/nav/SelectText.cpp index 0fcbe95..29d47e5 100644 --- a/WebKit/android/nav/SelectText.cpp +++ b/WebKit/android/nav/SelectText.cpp @@ -26,6 +26,7 @@ #define LOG_TAG "webcoreglue" #include "CachedPrefix.h" +#include "BidiResolver.h" #include "CachedRoot.h" #include "LayerAndroid.h" #include "SelectText.h" @@ -39,11 +40,101 @@ #include "SkRect.h" #include "SkRegion.h" #include "SkUtils.h" +#include "TextRun.h" #ifdef DEBUG_NAV_UI #include <wtf/text/CString.h> #endif +// TextRunIterator has been copied verbatim from GraphicsContext.cpp +namespace WebCore { + +class TextRunIterator { +public: + TextRunIterator() + : m_textRun(0) + , m_offset(0) + { + } + + TextRunIterator(const TextRun* textRun, unsigned offset) + : m_textRun(textRun) + , m_offset(offset) + { + } + + TextRunIterator(const TextRunIterator& other) + : m_textRun(other.m_textRun) + , m_offset(other.m_offset) + { + } + + unsigned offset() const { return m_offset; } + void increment() { m_offset++; } + bool atEnd() const { return !m_textRun || m_offset >= m_textRun->length(); } + UChar current() const { return (*m_textRun)[m_offset]; } + WTF::Unicode::Direction direction() const { return atEnd() ? WTF::Unicode::OtherNeutral : WTF::Unicode::direction(current()); } + + bool operator==(const TextRunIterator& other) + { + return m_offset == other.m_offset && m_textRun == other.m_textRun; + } + + bool operator!=(const TextRunIterator& other) { return !operator==(other); } + +private: + const TextRun* m_textRun; + int m_offset; +}; + +// ReverseBidi is a trimmed-down version of GraphicsContext::drawBidiText() +void ReverseBidi(UChar* chars, int len) { + using namespace WTF::Unicode; + WTF::Vector<UChar> result; + result.reserveCapacity(len); + TextRun run(chars, len); + BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; + bidiResolver.setStatus(BidiStatus(LeftToRight, LeftToRight, LeftToRight, + BidiContext::create(0, LeftToRight, false))); + bidiResolver.setPosition(TextRunIterator(&run, 0)); + bidiResolver.createBidiRunsForLine(TextRunIterator(&run, len)); + if (!bidiResolver.runCount()) + return; + BidiCharacterRun* bidiRun = bidiResolver.firstRun(); + while (bidiRun) { + int bidiStart = bidiRun->start(); + int bidiStop = bidiRun->stop(); + int size = result.size(); + int bidiCount = bidiStop - bidiStart; + result.append(chars + bidiStart, bidiCount); + if (bidiRun->level() % 2) { + UChar* start = &result[size]; + UChar* end = start + bidiCount; + // reverse the order of any RTL substrings + while (start < end) { + UChar temp = *start; + *start++ = *--end; + *end = temp; + } + start = &result[size]; + end = start + bidiCount - 1; + // if the RTL substring had a surrogate pair, restore its order + while (start < end) { + UChar trail = *start++; + if (!U16_IS_SURROGATE(trail)) + continue; + start[-1] = *start; // lead + *start++ = trail; + } + } + bidiRun = bidiRun->next(); + } + bidiResolver.deleteRuns(); + memcpy(chars, &result[0], len * sizeof(UChar)); +} + +} + namespace android { class CommonCheck : public SkBounder { @@ -264,6 +355,19 @@ public: } WebCore::String text() { + // the text has been copied in visual order. Reverse as needed if + // result contains right-to-left characters. + const uint16_t* start = mSelectText.begin(); + const uint16_t* end = mSelectText.end(); + while (start < end) { + SkUnichar ch = SkUTF16_NextUnichar(&start); + WTF::Unicode::Direction charDirection = WTF::Unicode::direction(ch); + if (WTF::Unicode::RightToLeftArabic == charDirection + || WTF::Unicode::RightToLeft == charDirection) { + WebCore::ReverseBidi(mSelectText.begin(), mSelectText.count()); + break; + } + } return WebCore::String(mSelectText.begin(), mSelectText.count()); } diff --git a/WebKit/android/nav/SelectText.h b/WebKit/android/nav/SelectText.h index 8174046..2e17a74 100644 --- a/WebKit/android/nav/SelectText.h +++ b/WebKit/android/nav/SelectText.h @@ -81,4 +81,10 @@ private: } +namespace WebCore { + +void ReverseBidi(UChar* chars, int len); + +} + #endif |