mirror of
https://github.com/apache/cordova-android.git
synced 2025-03-03 16:03:08 +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) {
|
||||
// Don't re-initialize on first load.
|
||||
if (loadedUrl != null) {
|
||||
appPlugin = null;
|
||||
pluginManager.init();
|
||||
}
|
||||
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