Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a08491a0 authored by Steve Block's avatar Steve Block
Browse files

Add a class to represent the set of sensitive features of a web application

This class is used to store the set of sensitive features for which the web app
is authorised. The data for which is passed as meta data with the intent. The
data is then used to set the security policy for features such as Geolocation
which request permission through the browser chrome.

Bug: 2766920
Change-Id: I2ff259dfd3b50d39bb05fbc187d4943c448d08d6
parent 074c08c4
Loading
Loading
Loading
Loading
+38 −10
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package android.webruntime;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.ComponentName;
@@ -54,6 +53,22 @@ public class WebRuntimeActivity extends Activity
    private URL mBaseUrl;
    private ImageView mSplashScreen;

    public static class SensitiveFeatures {
        // All of the sensitive features
        private boolean mGeolocation;
        // On Android, the Browser doesn't prompt for database access, so we don't require an
        // explicit permission here in the WebRuntimeActivity, and there's no Android system
        // permission required for it either.
        //private boolean mDatabase;

        public boolean getGeolocation() {
            return mGeolocation;
        }
        public void setGeolocation(boolean geolocation) {
            mGeolocation = geolocation;
        }
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
@@ -93,6 +108,10 @@ public class WebRuntimeActivity extends Activity
            Log.d(LOGTAG, "Invalid URL");
        }

        // All false by default, and reading non-existent bundle properties gives false too.
        final SensitiveFeatures sensitiveFeatures = new SensitiveFeatures();
        sensitiveFeatures.setGeolocation(metaData.getBoolean("android.webruntime.SensitiveFeaturesGeolocation"));

        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.web_runtime);
        mWebView = (WebView) findViewById(R.id.webview);
@@ -105,9 +124,8 @@ public class WebRuntimeActivity extends Activity
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                try {
                    URL newOrigin = new URL(url);
                    if (newOrigin.getHost().equals(mBaseUrl.getHost())) {
                    if (areSameOrigin(mBaseUrl, newOrigin)) {
                        // If simple same origin test passes, load in the webview.
                        // FIXME: We should do a more robust SOP check.
                        return false;
                    }
                } catch(MalformedURLException e) {
@@ -130,16 +148,20 @@ public class WebRuntimeActivity extends Activity
            }
        });

        // Use a custom WebChromeClient with geolocation permissions handling to always
        // allow or deny, based on the app's permissions.
        String packageName = componentName.getPackageName();
        final boolean allowed = packageManager.checkPermission(
                Manifest.permission.ACCESS_FINE_LOCATION, packageName)
                == PackageManager.PERMISSION_GRANTED;
        // Use a custom WebChromeClient with geolocation permissions handling.
        mWebView.setWebChromeClient(new WebChromeClient() {
            public void onGeolocationPermissionsShowPrompt(
                        String origin, GeolocationPermissions.Callback callback) {
                callback.invoke(origin, allowed, true);
                // Allow this origin if it has Geolocation permissions, otherwise deny.
                boolean allowed = false;
                if (sensitiveFeatures.getGeolocation()) {
                    try {
                        URL originUrl = new URL(origin);
                        allowed = areSameOrigin(mBaseUrl, originUrl);
                    } catch(MalformedURLException e) {
                    }
                }
                callback.invoke(origin, allowed, false);
            }
        });

@@ -173,4 +195,10 @@ public class WebRuntimeActivity extends Activity
        menu.add(0, 1, 0, "Menu item 2");
        return true;
    }

    private static boolean areSameOrigin(URL a, URL b) {
        int aPort = a.getPort() == -1 ? a.getDefaultPort() : a.getPort();
        int bPort = b.getPort() == -1 ? b.getDefaultPort() : b.getPort();
        return a.getProtocol().equals(b.getProtocol()) && aPort == bPort && a.getHost().equals(b.getHost());
    }
}