From a8f87e91a54a0e3003585f3abddf3b3ba10f9dcb Mon Sep 17 00:00:00 2001 From: Jani Hautakangas Date: Wed, 24 Jan 2024 02:52:00 +0200 Subject: [PATCH] wpe: Add onCloseWindow callback and use it in webdriver WebDriver needs to destroy wpeview when selenium requests to close the test --- .../com/wpe/webdriver/WebDriverActivity.kt | 18 +++++++++++++++--- wpe/src/main/cpp/Browser/Page.cpp | 16 ++++++++-------- wpe/src/main/java/com/wpe/wpe/Page.java | 4 ++++ .../java/com/wpe/wpeview/WPEChromeClient.java | 11 +++++++++++ wpe/src/main/java/com/wpe/wpeview/WPEView.java | 12 ++++++++++++ 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/tools/webdriver/src/main/java/com/wpe/webdriver/WebDriverActivity.kt b/tools/webdriver/src/main/java/com/wpe/webdriver/WebDriverActivity.kt index 1ef8b513e..de2a44647 100644 --- a/tools/webdriver/src/main/java/com/wpe/webdriver/WebDriverActivity.kt +++ b/tools/webdriver/src/main/java/com/wpe/webdriver/WebDriverActivity.kt @@ -10,12 +10,15 @@ import com.wpe.wpe.Browser import com.wpe.wpe.ProcessType import com.wpe.wpe.services.WPEServiceConnection import com.wpe.wpe.services.WPEServiceConnectionListener +import com.wpe.wpeview.WPEChromeClient import com.wpe.wpeview.WPEView class WebDriverActivity : AppCompatActivity() { private val LOGTAG = "WebDriver" + private lateinit var wpeView: WPEView + private val serviceConnectionDelegate: WPEServiceConnectionListener = object : WPEServiceConnectionListener { override fun onCleanExit(connection: WPEServiceConnection) { Log.d(LOGTAG, "onCleanExit for process: " + connection.pid) @@ -27,15 +30,24 @@ class WebDriverActivity : AppCompatActivity() { } } + private val wpeChromeClient: WPEChromeClient = object : WPEChromeClient { + override fun onCloseWindow(window: WPEView) { + Log.d(LOGTAG, "onCloseWindow") + setContentView(null) + wpeView.destroy() + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Browser.getInstance().isAutomationMode = true - val webView = WPEView(applicationContext) - setContentView(webView); + wpeView = WPEView(applicationContext) + wpeView.wpeChromeClient = wpeChromeClient + setContentView(wpeView) - webView.loadUrl("about:blank") + wpeView.loadUrl("about:blank") try { val processType = ProcessType.WebDriverProcess diff --git a/wpe/src/main/cpp/Browser/Page.cpp b/wpe/src/main/cpp/Browser/Page.cpp index f7029263e..8f44a249c 100644 --- a/wpe/src/main/cpp/Browser/Page.cpp +++ b/wpe/src/main/cpp/Browser/Page.cpp @@ -40,13 +40,11 @@ void handleCommitBuffer(void* context, WPEAndroidBuffer* buffer, int fenceID) WebKitWebView* createWebViewForAutomationCallback(WebKitAutomationSession* /*session*/, WebKitWebView* view) { - Logging::logDebug("createWebViewForAutomationCallback"); return view; } void automationStartedCallback(WebKitWebContext* /*context*/, WebKitAutomationSession* session, WebKitWebView* view) { - Logging::logDebug("AUTOMATIONSTARTED"); auto* info = webkit_application_info_new(); webkit_application_info_set_name(info, "MiniBrowser"); webkit_application_info_set_version(info, WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION, WEBKIT_MICRO_VERSION); @@ -71,6 +69,11 @@ class JNIPageCache final : public JNI::TypedClass { public: JNIPageCache(); + static void onClose(Page* page, WebKitWebView* /*webView*/) noexcept + { + callJavaMethod(getJNIPageCache().m_onClose, page->m_pageJavaInstance.get()); + } + static void onLoadChanged(Page* page, WebKitLoadEvent loadEvent, WebKitWebView* /*webView*/) noexcept { callJavaMethod(getJNIPageCache().m_onLoadChanged, page->m_pageJavaInstance.get(), static_cast(loadEvent)); @@ -127,6 +130,7 @@ class JNIPageCache final : public JNI::TypedClass { } } + const JNI::Method m_onClose; const JNI::Method m_onLoadChanged; const JNI::Method m_onLoadProgress; const JNI::Method m_onUriChanged; @@ -166,6 +170,7 @@ const JNIPageCache& getJNIPageCache() JNIPageCache::JNIPageCache() : JNI::TypedClass(true) + , m_onClose(getMethod("onClose")) , m_onLoadChanged(getMethod("onLoadChanged")) , m_onLoadProgress(getMethod("onLoadProgress")) , m_onUriChanged(getMethod("onUriChanged")) @@ -417,6 +422,7 @@ Page::Page(JNIEnv* env, JNIPage jniPage, int width, int height) webkit_web_view_set_input_method_context(m_webView, m_inputMethodContext.webKitInputMethodContext()); webkit_web_context_set_automation_allowed(Browser::instance().webContext(), automationMode); + m_signalHandlers.push_back(g_signal_connect_swapped(m_webView, "close", G_CALLBACK(JNIPageCache::onClose), this)); m_signalHandlers.push_back( g_signal_connect_swapped(m_webView, "load-changed", G_CALLBACK(JNIPageCache::onLoadChanged), this)); m_signalHandlers.push_back(g_signal_connect_swapped( @@ -435,12 +441,6 @@ Page::Page(JNIEnv* env, JNIPage jniPage, int width, int height) g_signal_connect( Browser::instance().webContext(), "automation-started", G_CALLBACK(automationStartedCallback), m_webView); } - - if (webkit_web_view_is_controlled_by_automation(m_webView) == TRUE) { - Logging::logDebug("FOOBAR"); - } else { - Logging::logDebug("FOOBAR - NOT"); - } } void Page::close() noexcept diff --git a/wpe/src/main/java/com/wpe/wpe/Page.java b/wpe/src/main/java/com/wpe/wpe/Page.java index e44ef85ca..91130dd29 100644 --- a/wpe/src/main/java/com/wpe/wpe/Page.java +++ b/wpe/src/main/java/com/wpe/wpe/Page.java @@ -159,6 +159,10 @@ public void onLoadChanged(int loadEvent) { } } + @Keep + public void onClose() { + wpeView.onClose(); + } @Keep public void onLoadProgress(double progress) { wpeView.onLoadProgress(progress); diff --git a/wpe/src/main/java/com/wpe/wpeview/WPEChromeClient.java b/wpe/src/main/java/com/wpe/wpeview/WPEChromeClient.java index d9af22352..7ef316883 100644 --- a/wpe/src/main/java/com/wpe/wpeview/WPEChromeClient.java +++ b/wpe/src/main/java/com/wpe/wpeview/WPEChromeClient.java @@ -27,6 +27,17 @@ import androidx.annotation.NonNull; public interface WPEChromeClient { + /** + * Notify the host application to close the given WebView and remove it + * from the view system if necessary. At this point, WebCore has stopped + * any loading in this window and has removed any cross-scripting ability + * in javascript. + *

+ * + * @param window The WebView that needs to be closed. + */ + + default void onCloseWindow(@NonNull WPEView window) {} /** * Tell the host application the current progress while loading a page. * @param view The WPEView that initiated the callback. diff --git a/wpe/src/main/java/com/wpe/wpeview/WPEView.java b/wpe/src/main/java/com/wpe/wpeview/WPEView.java index b627fc0d7..e926b7f95 100644 --- a/wpe/src/main/java/com/wpe/wpeview/WPEView.java +++ b/wpe/src/main/java/com/wpe/wpeview/WPEView.java @@ -125,6 +125,11 @@ public void onLoadChanged(int loadEvent) { } } + public void onClose() { + if (wpeChromeClient != null) + wpeChromeClient.onCloseWindow(this); + } + public void onLoadProgress(double progress) { currentLoadProgress = Math.max(0, Math.min(100, (int)Math.round(progress * 100))); if (wpeChromeClient != null) @@ -166,6 +171,13 @@ public void onExitFullscreenMode() { /************** PUBLIC WPEView API *******************/ + /** + * Destroys the internal state of this WebView. This method should be called + * after this WebView has been removed from the view system. No other + * methods may be called on this WebView after destroy. + */ + public void destroy() { page.destroy(); } + /** * Gets the page associated with this WPEView. * @return the associated page.