Skip to content

Commit

Permalink
8264501: UIWebView for iOS is deprecated
Browse files Browse the repository at this point in the history
Reviewed-by: jvos
  • Loading branch information
Jose Pereda committed Mar 31, 2021
1 parent ed5cfe7 commit d80b8ad
Show file tree
Hide file tree
Showing 9 changed files with 247 additions and 89 deletions.
10 changes: 5 additions & 5 deletions buildSrc/ios.gradle
Expand Up @@ -378,7 +378,7 @@ IOS.font.x86_64.linkFlags = ["-arch_only", archX86_64, "-syslibroot", sdkPath(iP
IOS.font.x86_64.lib = "javafx_font_${archX86_64}"

IOS.webview = [:]
IOS.webview.lib = "javafx_ios_webnode"
IOS.webview.lib = "webview"
IOS.webview.javahInclude = ["javafx/scene/web/*"]
IOS.webview.variants = ["arm", "arm64", "x86", "x86_64"];

Expand All @@ -388,31 +388,31 @@ IOS.webview.arm.compiler = compiler
IOS.webview.arm.ccFlags = [ccFlags, "-arch", archArm, "-isysroot", sdkPath(iPhoneOS)].flatten()
IOS.webview.arm.linker = linker
IOS.webview.arm.linkFlags = ["-arch_only", archArm, "-syslibroot", sdkPath(iPhoneOS), linkFlags].flatten()
IOS.webview.arm.lib = "javafx_ios_webnode_${archArm}"
IOS.webview.arm.lib = "webview_${archArm}"

IOS.webview.arm64 = [:]
IOS.webview.arm64.nativeSource = file("${project("web").projectDir}/src/ios/native")
IOS.webview.arm64.compiler = compiler
IOS.webview.arm64.ccFlags = [ccFlags, "-arch", archArm64, "-isysroot", sdkPath(iPhoneOS)].flatten()
IOS.webview.arm64.linker = linker
IOS.webview.arm64.linkFlags = ["-arch_only", archArm64, "-syslibroot", sdkPath(iPhoneOS), linkFlags].flatten()
IOS.webview.arm64.lib = "javafx_ios_webnode_${archArm64}"
IOS.webview.arm64.lib = "webview_${archArm64}"

IOS.webview.x86 = [:]
IOS.webview.x86.nativeSource = [IOS.webview.arm.nativeSource].flatten()
IOS.webview.x86.compiler = compiler
IOS.webview.x86.ccFlags = [ccFlags, "-arch", archX86, "-isysroot", sdkPath(iPhoneSim)].flatten()
IOS.webview.x86.linker = linker
IOS.webview.x86.linkFlags = ["-arch_only", archX86, "-syslibroot", sdkPath(iPhoneSim), linkFlags].flatten()
IOS.webview.x86.lib = "javafx_ios_webnode_${archX86}"
IOS.webview.x86.lib = "webview_${archX86}"

IOS.webview.x86_64 = [:]
IOS.webview.x86_64.nativeSource = [IOS.webview.arm.nativeSource].flatten()
IOS.webview.x86_64.compiler = compiler
IOS.webview.x86_64.ccFlags = [ccFlags, "-arch", archX86_64, "-isysroot", sdkPath(iPhoneSim)].flatten()
IOS.webview.x86_64.linker = linker
IOS.webview.x86_64.linkFlags = ["-arch_only", archX86_64, "-syslibroot", sdkPath(iPhoneSim), linkFlags].flatten()
IOS.webview.x86_64.lib = "javafx_ios_webnode_${archX86_64}"
IOS.webview.x86_64.lib = "webview_${archX86_64}"

IOS.media = [:]
IOS.media.lib = "jfxmedia"
Expand Down
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package com.sun.javafx.sg.prism.web;

import com.sun.javafx.geom.BaseBounds;
import com.sun.javafx.geom.RectBounds;
import com.sun.javafx.sg.prism.NGGroup;
import com.sun.prism.Graphics;

public final class NGWebView extends NGGroup {
private volatile float width, height;

public void resize(float w, float h) {
if (width != w || height != h) {
width = w;
height = h;
geometryChanged();
}
}

// Invoked on JavaFX User Thread.
public void update() {
}

public void requestRender() {
visualsChanged();
}

private final RectBounds destBounds = new RectBounds();

@Override
protected void doRender(Graphics g) {
renderContent(g);
}

@Override
public void setTransformedBounds(BaseBounds bounds, boolean byTransformChangeOnly) {
super.setTransformedBounds(bounds, byTransformChangeOnly);
}

// Invoked on Render Thread.
@Override
protected void renderContent(Graphics g) {
if (g == null || width <= 0 || height <= 0) {
return;
}
g.getTransformNoClone().transform(transformedBounds, destBounds);
}

@Override public boolean hasOverlappingContents() {
return false;
}

@Override protected boolean hasVisuals() {
return true;
}
}
Expand Up @@ -256,7 +256,7 @@ private String callWorker(String methodName, String args) throws CallException {
}

private Method[] getPublicMethods(final Class clz) {
Method[] m = clz.getMethods();
Method[] m = clz.getDeclaredMethods();
ArrayList<Method> am = new ArrayList<Method>();
for (int i = 0; i < m.length; i++) {
if (Modifier.isPublic(m[i].getModifiers())){
Expand Down
Expand Up @@ -121,10 +121,10 @@ private void populateObject(String jsName, ExportedJavaObject jsObj) {
sb = sb.append(getJavaBridge()).append(".exportJSObject(").append(
getJavaBridge()).append("['").append(jsName).append("'])");

Integer jsId = (Integer) webEngine.executeScript(sb.toString());
if (jsId != null) {
exportedObjectsByJSIds.put(jsId.toString(), jsObj);
jsIdsByExportedObjects.put(jsObj, jsId.toString());
String jsId = String.valueOf(webEngine.executeScript(sb.toString()));
if (!jsId.equals("null")) {
exportedObjectsByJSIds.put(jsId, jsObj);
jsIdsByExportedObjects.put(jsObj, jsId);
}
else {
System.out.println("[JVDBG] Error, jsId = null for "+jsName);
Expand Down Expand Up @@ -204,12 +204,14 @@ void populateJavaObjects() {

@Override
public void onLoadStarted() {
populateJavaObjects();
objectIdCounter.set(0);
exportedObjectsByJavaObject.clear();
// TODO: free all unnamed ExportedJavaObjects
}

@Override
public void onLoadFinished() {
populateJavaObjects();
}

@Override
Expand Down
31 changes: 20 additions & 11 deletions modules/javafx.web/src/ios/java/javafx/scene/web/WebEngine.java
Expand Up @@ -562,18 +562,26 @@ public void loadContent(String content) {
*/
public void loadContent(String content, String contentType) {
checkThread();
LoadWorker lw = (LoadWorker) getLoadWorker();
if (lw != null) {
lw.cancelAndReset();
}
_loadContent(view.get().getNativeHandle(), content);
}

/* Loads the given content directly */
private native void _loadContent(long handle, String content);

/* Reloads the current content directly */
private native void _reload(long handle);

/**
* Reloads the current page, whether loaded from URL or directly from a String in
* one of the {@code loadContent} methods.
*/
public void reload() {
checkThread();
_reload(view.get().getNativeHandle());
}

/**
Expand Down Expand Up @@ -603,11 +611,12 @@ public Object executeScript(String script) {
b.append(escapeScript(script));
b.append("')");
String retVal = _executeScript(view.get().getNativeHandle(), b.toString());

try {
return js2javaBridge.decode(retVal);
} catch (Exception ex) {
System.err.println("Couldn't parse arguments. " + ex);
if (retVal != null) {
try {
return js2javaBridge.decode(retVal);
} catch (Exception ex) {
System.err.println("Couldn't parse arguments. " + ex);
}
}
return null;
}
Expand Down Expand Up @@ -860,9 +869,9 @@ void setPageListener(PageListener listener) {
updateState(Worker.State.SCHEDULED);
updateState(Worker.State.RUNNING);
pageListener.onLoadStarted();
pageListener.onLoadFinished();
updateProgress(1.0);
updateState(Worker.State.SUCCEEDED);
pageListener.onLoadFinished();
}
}
}
Expand Down Expand Up @@ -894,7 +903,7 @@ Document getCurrentDocument () {
document = builder.parse(new InputSource(new StringReader(pageContent)));
}
catch (Exception e) {
e.printStackTrace();
System.err.println("Error parsing html: " + e.getLocalizedMessage());
}
return document;
}
Expand All @@ -903,13 +912,13 @@ void notifyLoadFinished(String loc, String content) {
synchronized (loadedLock) {
this.pageContent = "<html>"+content+"</html>";
loaded = true;
updateProgress(1.0);
updateState(Worker.State.SUCCEEDED);
location.set(loc);
document.invalidate(true);
if (pageListener != null) {
pageListener.onLoadFinished();
}
updateProgress(1.0);
location.set(loc);
document.invalidate(true);
updateState(Worker.State.SUCCEEDED);
}
}

Expand Down
49 changes: 36 additions & 13 deletions modules/javafx.web/src/ios/java/javafx/scene/web/WebView.java
Expand Up @@ -26,6 +26,7 @@
package javafx.scene.web;


import javafx.application.Platform;
import javafx.css.CssMetaData;
import javafx.css.StyleableBooleanProperty;
import javafx.css.StyleableDoubleProperty;
Expand All @@ -45,6 +46,7 @@
import com.sun.java.scene.web.WebViewHelper;

import com.sun.javafx.sg.prism.NGNode;
import com.sun.javafx.sg.prism.web.NGWebView;
import com.sun.javafx.tk.TKPulseListener;
import com.sun.javafx.tk.Toolkit;
import java.util.ArrayList;
Expand Down Expand Up @@ -103,9 +105,11 @@ public boolean doComputeContains(Node node, double localX, double localY) {

@Override
public void doPickNodeLocal(Node node, PickRay localPickRay, PickResultChooser result) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
// Not supported yet
}
});

System.loadLibrary("webview");
}

private static final boolean DEFAULT_CONTEXT_MENU_ENABLED = true;
Expand All @@ -122,6 +126,7 @@ public void doPickNodeLocal(Node node, PickRay localPickRay, PickResultChooser r
private final WebEngine engine;
// pointer to native WebViewImpl
private final long handle;
private boolean nativeVisible = true;

/**
* The stage pulse listener registered with the toolkit.
Expand Down Expand Up @@ -340,7 +345,7 @@ public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValu

@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
_setVisible(handle, newValue);
setNativeVisible(handle, newValue);
}
});
}
Expand Down Expand Up @@ -1029,11 +1034,13 @@ && getScene().getWindow() != null
if (reallyVisible) {
if (NodeHelper.isDirty(this, DirtyBits.WEBVIEW_VIEW)) {
SceneHelper.setAllowPGAccess(true);
//getPGWebView().update(); // creates new render queues
final NGWebView peer = NodeHelper.getPeer(this);
peer.update(); // creates new render queues
SceneHelper.setAllowPGAccess(false);
}
setNativeVisible(handle, true);
} else {
_setVisible(handle, false);
setNativeVisible(handle, false);
}
}

Expand All @@ -1042,13 +1049,16 @@ && getScene().getWindow() != null
}

// Node stuff
{
// To initialize the class helper at the beginning each constructor of this class
WebViewHelper.initHelper(this);
}

/*
* Note: This method MUST only be called via its accessor method.
*/
private NGNode doCreatePeer() {
// return new NGWebView();
return null; // iOS doesn't need this method.
return new NGWebView();
}

/*
Expand All @@ -1072,13 +1082,13 @@ private boolean doComputeContains(double localX, double localY) {
* Note: This method MUST only be called via its accessor method.
*/
private void doUpdatePeer() {
//PGWebView peer = getPGWebView();
final NGWebView peer = NodeHelper.getPeer(this);

if (NodeHelper.isDirty(this, DirtyBits.NODE_GEOMETRY)) {
//peer.resize((float)getWidth(), (float)getHeight());
peer.resize((float)getWidth(), (float)getHeight());
}
if (NodeHelper.isDirty(this, DirtyBits.WEBVIEW_VIEW)) {
//peer.requestRender();
peer.requestRender();
}
}

Expand Down Expand Up @@ -1107,21 +1117,34 @@ long getNativeHandle() {
return handle;
}

private void setNativeVisible(long handle, boolean v) {
if (nativeVisible != v) {
nativeVisible = v;
_setVisible(handle, v);
}
}

// native callbacks
private void notifyLoadStarted() {
engine.notifyLoadStarted();
checkThreadAndRun(engine::notifyLoadStarted);
}
private void notifyLoadFinished(String loc, String content) {
engine.notifyLoadFinished(loc, content);
checkThreadAndRun(() -> engine.notifyLoadFinished(loc, content));
}
private void notifyLoadFailed() {
engine.notifyLoadFailed();
checkThreadAndRun(engine::notifyLoadFailed);
}
private void notifyJavaCall(String arg) {
engine.notifyJavaCall(arg);
checkThreadAndRun(() -> engine.notifyJavaCall(arg));
}

private static void checkThreadAndRun(Runnable runnable) {
if (Platform.isFxApplicationThread()) {
runnable.run();
} else {
Platform.runLater(runnable);
}
}

/* Inits native WebView and returns its pointer in the given array */
private native void _initWebView(long[] nativeHandle);
Expand Down

1 comment on commit d80b8ad

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.