cordova-android icon indicating copy to clipboard operation
cordova-android copied to clipboard

Ignoring exec() from previous page load.

Open safayildirim opened this issue 4 years ago • 4 comments

Bug Report

Problem

As you know, when orientation change on android platform, activity is killed and regenerated. Because of this, cordova platform is also regenerated. In this point, until cordova-android 9 version, all versions has executed the pluginInitialized method everytime when orientation changed but on cordova-android 9 it sometimes executes, sometimes not. When it is not called, log prints below lines.

gap_init called from restricted origin:
D/CordovaBridge: Ignoring exec() from previous page load.

After I searched for a solution on platform source code, I noticed that below code section is removed on cordova-android 9. When I readded lines on information section below, it works perfectly. Finally my question is that what issue prevent cordova calling pluginInitialize method every time when orientation changed?

I added some logs to CordovaBridge.java file. pluginInitialize method is not called because in below method jsMessageQueue.isBridgeEnabled() is returns false.

private boolean verifySecret(String action, int bridgeSecret) throws IllegalAccessException {
        Log.d("TAG", action + "---" + jsMessageQueue.isBridgeEnabled());
        if (!jsMessageQueue.isBridgeEnabled()) { //This line returns false sometimes.
            if (bridgeSecret == -1) {
                LOG.d(LOG_TAG, action + " call made before bridge was enabled.");
            } else {
                LOG.d(LOG_TAG, "Ignoring " + action + " from previous page load.");
            }
            return false;
        }
        // Bridge secret wrong and bridge not due to it being from the previous page.
        if (expectedBridgeSecret < 0 || bridgeSecret != expectedBridgeSecret) {
            LOG.e(LOG_TAG, "Bridge access attempt with wrong secret token, possibly from malicious code. Disabling exec() bridge!");
            clearBridgeSecret();
            throw new IllegalAccessException();
        }
        return true;
    }

When jsMessageQueue.isBridgeEnabled() returns false, no method on onDeviceReady event is called. These are all logs.

I/CordovaActivity: Apache Cordova native platform version 9.0.0 is starting
D/CordovaActivity: CordovaActivity.onCreate()
D/SystemWebViewEngine: CordovaWebView is running on device made by: HUAWEI
D/PluginManager: init()
D/CordovaWebViewImpl: >>> loadUrl(file:///android_asset/www/index.html)
D/ActivityThread: add activity client record, r= ActivityRecord{d6daa05 token=android.os.BinderProxy@c3ccfde {com.example.hmsappmessaging/com.example.application.MainActivity}} token= android.os.BinderProxy@c3ccfde
D/CordovaActivity: Started the activity.
W/cr_AwContents: Application attempted to call on a destroyed WebView
    java.lang.Throwable
        at org.chromium.android_webview.AwContents.p(chromium-TrichromeWebViewGoogle.aab-stable-428014133:2)
        at vM.loadingStateChanged(chromium-TrichromeWebViewGoogle.aab-stable-428014133:2)
        at android.os.MessageQueue.nativePollOnce(Native Method)
        at android.os.MessageQueue.next(MessageQueue.java:363)
        at android.os.Looper.loop(Looper.java:173)
        at android.app.ActivityThread.main(ActivityThread.java:8178)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
D/HiTouch_PressGestureDetector: onAttached, package=com.example.hmsappmessaging, windowType=1, mHiTouchRestricted=false
D/mali_winsys: EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000
D/Whitelist: java.lang.NullPointerException: Attempt to invoke interface method 'int java.lang.CharSequence.length()' on a null object reference
D/Whitelist: java.lang.NullPointerException: Attempt to invoke interface method 'int java.lang.CharSequence.length()' on a null object reference
E/CordovaBridge: gap_init called from restricted origin: 
D/TAG: setBridgeMode() called with: value = [-1]
D/CordovaWebViewImpl: onPageDidNavigate(file:///android_asset/www/index.html)
D/CordovaWebViewImpl: onPageFinished(file:///android_asset/www/index.html)
D/TAG: jsExec() called with: bridgeSecret = [0]
D/TAG: exec()---false
D/CordovaBridge: Ignoring exec() from previous page load.
D/TAG: jsExec() called with: bridgeSecret = [0]
D/TAG: exec()---false
D/CordovaBridge: Ignoring exec() from previous page load.
D/TAG: jsExec() called with: bridgeSecret = [0]
D/TAG: exec()---false
D/CordovaBridge: Ignoring exec() from previous page load.
I/chromium: [INFO:CONSOLE(23)] "Running [email protected]", source: file:///android_asset/www/js/index.js (23)
D/TAG: jsExec() called with: bridgeSecret = [0]
D/TAG: exec()---false
D/CordovaBridge: Ignoring exec() from previous page load.
D/TAG: jsExec() called with: bridgeSecret = [0
D/TAG: exec()---false
D/CordovaBridge: Ignoring exec() from previous page load.
D/TAG: jsExec() called with: bridgeSecret = [0]
D/TAG: exec()---false
D/CordovaBridge: Ignoring exec() from previous page load.
D/TAG: jsExec() called with: bridgeSecret = [0]
D/TAG: exec()---false
D/CordovaBridge: Ignoring exec() from previous page load.
D/mali_winsys: EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 

What is expected to happen?

When orientation is changed, pluginInitialize method on native must be called eveytime.

What does actually happen?

It is called sometimes, sometimes not.

Information

When I add below lines to the cordova.js file, everything works perfectly. These lines are removed from platform on cordova-android 9.0.0.


var utils = require('cordova/utils');
// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
// We replace it so that properties that can't be clobbered can instead be overridden.
function replaceNavigator (origNavigator) {
    var CordovaNavigator = function () {};
    CordovaNavigator.prototype = origNavigator;
    var newNavigator = new CordovaNavigator();
    // This work-around really only applies to new APIs that are newer than Function.bind.
    // Without it, APIs such as getGamepads() break.
    if (CordovaNavigator.bind) {
        for (var key in origNavigator) {
            if (typeof origNavigator[key] === 'function') {
                newNavigator[key] = origNavigator[key].bind(origNavigator);
            } else {
                (function (k) {
                    utils.defineGetterSetter(newNavigator, key, function () {
                        return origNavigator[k];
                    });
                })(key);
            }
        }
    }
    return newNavigator;
}

Command or Code

Just change orientation.

Environment, Platform, Device

Windows 10 Cordova CLI 10.0.0 Cordova Android 9.0.0 Huawei P Smart Pro(probably all devices)

Version information

❯ cordova -v 10.0.0 ❯ cordova platform ls Installed platforms: android 9.0.0

Checklist

  • [X] I searched for existing GitHub issues
  • [X] I updated all Cordova tooling to most recent version
  • [X] I included all the necessary information above

safayildirim avatar Jan 18 '21 13:01 safayildirim

No one help?

safayildirim avatar Jan 26 '21 05:01 safayildirim

I don't understand most of what you're saying, but I'm getting this same error 100% of the time on Fire TV. Instead of the plugin class's execute function being called, the callbacks pile up in the cordova object in the browser and aren't processed at all. This message doesn't actually say anything meaningful.

steve-taylor avatar Dec 24 '21 05:12 steve-taylor

anyone know how fix this problem?

asv avatar Aug 29 '22 13:08 asv

The main issue is your webview instance is being destroyed. When this happens, Cordova needs to create a new webview and reload.

This is problematic because just because the webview has reloaded, doesn't mean the state in native plugins have disappeared, but their state is definitely invalid (any callback references they hold and such would be invalid). This is a "hard-to-recover" kind of issue.

Ignoring exec() from previous page load. also is intentional in these circumstances. It's simply stating that you had exec calls queued on the native side that was created from a previous webview, so those calls are no longer valid.

In order to really move this along, we first need to understand what is causing the webview to be destroyed in the first place. I have apps that supports multiple orientations and they do not exhibit this issue (my test devices are mainly Samsung, Google Pixel, & emulators. I do not have Huawei on hand). So it's either not as simple as an orientation change, or it could be that this is specific to certain devices, or perhaps even a webview version.

breautek avatar Aug 29 '22 14:08 breautek