mirror of
https://github.com/apache/cordova-android.git
synced 2025-03-04 00:13:20 +08:00
CB-11292 fix broken MessageChannel after plugins are recreated
This closes #307
This commit is contained in:
parent
9738079c42
commit
ecb99c963d
@ -135,6 +135,7 @@ public class CordovaWebViewImpl implements CordovaWebView {
|
|||||||
if (recreatePlugins) {
|
if (recreatePlugins) {
|
||||||
// Don't re-initialize on first load.
|
// Don't re-initialize on first load.
|
||||||
if (loadedUrl != null) {
|
if (loadedUrl != null) {
|
||||||
|
appPlugin = null;
|
||||||
pluginManager.init();
|
pluginManager.init();
|
||||||
}
|
}
|
||||||
loadedUrl = url;
|
loadedUrl = url;
|
||||||
|
@ -0,0 +1,110 @@
|
|||||||
|
package org.apache.cordova.test;
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.inputmethod.BaseInputConnection;
|
||||||
|
|
||||||
|
import org.apache.cordova.CallbackContext;
|
||||||
|
import org.apache.cordova.CordovaWebViewImpl;
|
||||||
|
import org.apache.cordova.PluginManager;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public class MessageChannelMultiPageTest extends BaseCordovaIntegrationTest {
|
||||||
|
private static final String START_URL = "file:///android_asset/www/backbuttonmultipage/index.html";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
setUpWithStartUrl(START_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//test that after a page load the cached callback id and the live callback id match
|
||||||
|
//this is to prevent a regression
|
||||||
|
//the issue was that CordovaWebViewImpl's cached instance of CoreAndroid would become stale on page load
|
||||||
|
//this is because the cached instance was not being cleared when the pluginManager was reset on page load
|
||||||
|
//the plugin manager would get a new instance which would be updated with a new callback id
|
||||||
|
//the cached instance's message channel callback id would become stale
|
||||||
|
//effectively this caused message channel events to not be delivered
|
||||||
|
public void testThatCachedCallbackIdIsValid() throws Throwable {
|
||||||
|
Class cordovaWebViewImpl = CordovaWebViewImpl.class;
|
||||||
|
//send a test event - this initializes cordovaWebViewImpl.appPlugin (the cached instance of CoreAndroid)
|
||||||
|
Method method = cordovaWebViewImpl.getDeclaredMethod("sendJavascriptEvent", String.class);
|
||||||
|
method.setAccessible(true);
|
||||||
|
method.invoke(cordovaWebView, "testEvent");
|
||||||
|
sleep(1000);
|
||||||
|
|
||||||
|
//load a page - this resets the plugin manager and nulls cordovaWebViewImpl.appPlugin
|
||||||
|
//(previously this resets plugin manager but did not null cordovaWebViewImpl.appPlugin, leading to the issue)
|
||||||
|
runTestOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
cordovaWebView.loadUrl(START_URL);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertEquals(START_URL, testActivity.onPageFinishedUrl.take());
|
||||||
|
|
||||||
|
//send a test event - this initializes cordovaWebViewImpl.appPlugin (the cached instance of CoreAndroid)
|
||||||
|
method.invoke(cordovaWebView, "testEvent");
|
||||||
|
sleep(1000);
|
||||||
|
|
||||||
|
//get reference to package protected class CoreAndroid
|
||||||
|
Class coreAndroid = Class.forName("org.apache.cordova.CoreAndroid");
|
||||||
|
|
||||||
|
//get cached CoreAndroid
|
||||||
|
Field appPluginField = cordovaWebViewImpl.getDeclaredField("appPlugin");
|
||||||
|
appPluginField.setAccessible(true);
|
||||||
|
Object cachedAppPlugin = appPluginField.get(cordovaWebView);
|
||||||
|
//get cached CallbackContext
|
||||||
|
Field messageChannelField = coreAndroid.getDeclaredField("messageChannel");
|
||||||
|
messageChannelField.setAccessible(true);
|
||||||
|
CallbackContext cachedCallbackContext = (CallbackContext) messageChannelField.get(cachedAppPlugin);
|
||||||
|
|
||||||
|
//get live CoreAndroid
|
||||||
|
PluginManager pluginManager = MessageChannelMultiPageTest.this.cordovaWebView.getPluginManager();
|
||||||
|
Field coreAndroidPluginNameField = coreAndroid.getField("PLUGIN_NAME");
|
||||||
|
String coreAndroidPluginName = (String) coreAndroidPluginNameField.get(null);
|
||||||
|
Object liveAppPlugin = pluginManager.getPlugin(coreAndroidPluginName);
|
||||||
|
//get live CallbackContext
|
||||||
|
CallbackContext liveCallbackContext = (CallbackContext) messageChannelField.get(liveAppPlugin);
|
||||||
|
|
||||||
|
//get callback id from live callbackcontext
|
||||||
|
String liveCallbackId = (liveCallbackContext != null) ? liveCallbackContext.getCallbackId() : null;
|
||||||
|
//get callback id from cached callbackcontext
|
||||||
|
String cachedCallbackId = (cachedCallbackContext != null) ? cachedCallbackContext.getCallbackId() : null;
|
||||||
|
|
||||||
|
//verify that the live message channel has been initialized
|
||||||
|
assertNotNull(liveCallbackId);
|
||||||
|
//verify that the cached message channel and the live message channel have the same id
|
||||||
|
assertEquals(liveCallbackId, cachedCallbackId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sleep(int timeout) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(timeout);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
fail("Unexpected Timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user