Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java class only declaration no definition

New to Java and debugging the WebView android app which does not update properly. To find out what happens in onDraw() of WebView the source code here http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.2.2_r1/android/webkit/WebView.java?av=f

shows the onDraw() class calls

 mProvider.init(javaScriptInterfaces, privateBrowsing);

the mProvider.init(...) is here http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.2.2_r1/android/webkit/WebViewProvider.java#WebViewProvider.init%28java.util.Map%2Cboolean%29

But only declaration is present no definition. In c++ the definitions are in cpp files. Is there any equivalent in java ?.

like image 492
Talespin_Kit Avatar asked Mar 12 '26 16:03

Talespin_Kit


1 Answers

mProvider.init(javaScriptInterfaces, privateBrowsing);

Is implemented by WebViewClassic

The relevant grepcode link is here.

In case link is not available here is the raw method:

@Override
public void init(Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
    Context context = mContext;

    // Used by the chrome stack to find application paths
    JniUtil.setContext(context);

    mCallbackProxy = new CallbackProxy(context, this);
    mViewManager = new ViewManager(this);
    L10nUtils.setApplicationContext(context.getApplicationContext());
    mWebViewCore = new WebViewCore(context, this, mCallbackProxy, javaScriptInterfaces);
    mDatabase = WebViewDatabaseClassic.getInstance(context);
    mScroller = new OverScroller(context, null, 0, 0, false); //TODO Use OverScroller's flywheel
    mZoomManager = new ZoomManager(this, mCallbackProxy);

    /* The init method must follow the creation of certain member variables,
     * such as the mZoomManager.
     */
    init();
    setupPackageListener(context);
    setupProxyListener(context);
    setupTrustStorageListener(context);
    updateMultiTouchSupport(context);

    if (privateBrowsing) {
        startPrivateBrowsing();
    }

    mAutoFillData = new WebViewCore.AutoFillData();
    mEditTextScroller = new Scroller(context);
}

EDIT :

Since you are interested about mProvider more than init() let's go through the path of mProvider.

First we see it defined in the WebView class.

private WebViewProvider mProvider;

private void ensureProviderCreated() {
    checkThread();
    if (mProvider == null) {
        // As this can get called during the base class constructor chain, pass the minimum
        // number of dependencies here; the rest are deferred to init().
        mProvider = getFactory().createWebView(this, new PrivateAccess());
    }
}

From the block above we can see that the ensureProviderCreater() method initializes the mProvider variable. This method is called in the non-deprecated constructor of the WebView class.

First the getFactory() method is called so let's look at that:

private static synchronized WebViewFactoryProvider getFactory() {
    // For now the main purpose of this function (and the factory abstration) is to keep
    // us honest and minimize usage of WebViewClassic internals when binding the proxy.
    checkThread();
    return WebViewFactory.getProvider();
}

Let's leave the checkThread() be and take a look at WebViewFactory.getProvider(); instead.

static WebViewFactoryProvider getProvider() {
    synchronized (sProviderLock) {
        // For now the main purpose of this function (and the factory abstraction) is to keep
        // us honest and minimize usage of WebViewClassic internals when binding the proxy.
        if (sProviderInstance != null) return sProviderInstance;

        // For debug builds, we allow a system property to specify that we should use the
        // Chromium powered WebView. This enables us to switch between implementations
        // at runtime. For user (release) builds, don't allow this.
        if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("webview.use_chromium", false)) {
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
            try {
                sProviderInstance = loadChromiumProvider();
                if (DEBUG) Log.v(LOGTAG, "Loaded Chromium provider: " + sProviderInstance);
            } finally {
                StrictMode.setThreadPolicy(oldPolicy);
            }
        }

        if (sProviderInstance == null) {
            if (DEBUG) Log.v(LOGTAG, "Falling back to default provider: "
                    + DEFAULT_WEBVIEW_FACTORY);
            sProviderInstance = getFactoryByName(DEFAULT_WEBVIEW_FACTORY,
                    WebViewFactory.class.getClassLoader());
            if (sProviderInstance == null) {
                if (DEBUG) Log.v(LOGTAG, "Falling back to explicit linkage");
                sProviderInstance = new WebViewClassic.Factory();
            }
        }
        return sProviderInstance;
    }
}

It may not be immediately obvious what is happening here but here's the jist of it.

It checks if the build is debug-enabled, if there is a system variable "webview.use_chromium" and if it's set to "true".

If all of the conditions above occur then the chromium webview provider gets loaded (for the reasons mentioned in the comments in the block above).

If the condition is not met (e.g. the build is not in devmode) we ask the class loader to load DEFAULT_WEBVIEW_FACTORY by name which actually resolves to android.webkit.WebViewClassic$Factory (Can you start to see it all coming together now? :) )

So in the end unless we're meeting some specific conditions WebViewFactory.getProvider() will return the inner Factory class of the WebViewClassic class - WebViewClassic.Factory.

So let's revert back to our initial ensureProviderCreated() and see where we stand at the moment.

private void ensureProviderCreated() {
    checkThread();
    if (mProvider == null) {
        // As this can get called during the base class constructor chain, pass the minimum
        // number of dependencies here; the rest are deferred to init().
        mProvider = getFactory().createWebView(this, new PrivateAccess());
    }
}

OK, so we now know that getFactory() will return WebViewClassic.Factory, so now we only need to inspect the createWebView method of that factory.

@Override
public WebViewProvider createWebView(WebView webView, WebView.PrivateAccess privateAccess) {
    return new WebViewClassic(webView, privateAccess);
}

As you can plainly see it is quite straightforward, it returns a new instance of WebViewClassic passing it the WebView object since we called it from WebView with this as well as the privateAccess argument will be the new PrivateAccess() we passed as well.

For completion sake here's the constructor that is called for WebViewClassic:

public WebViewClassic(WebView webView, WebView.PrivateAccess privateAccess) {
    mWebView = webView;
    mWebViewPrivate = privateAccess;
    mContext = webView.getContext();
}

Hopefully this should clear up your confusion about what the heck is mProvider and how is it made. :)

like image 171
Ceiling Gecko Avatar answered Mar 14 '26 04:03

Ceiling Gecko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!