Bladeren bron

tmp backup

isundil 8 jaren geleden
bovenliggende
commit
1f91b522b5

+ 43 - 53
app/src/main/java/com/knacki/mimou/activity/MainActivity.java

@@ -5,7 +5,6 @@ import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.net.Uri;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -15,24 +14,23 @@ import android.support.v7.app.AlertDialog;
 import android.support.v7.app.AppCompatActivity;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.webkit.WebChromeClient;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
 
-import com.knacki.mimou.BuildConfig;
+import com.knacki.mimou.R;
+import com.knacki.mimou.bridge.CookieManager;
 import com.knacki.mimou.bridge.JavascriptFunction;
-import com.knacki.mimou.preference.CredentialHolder;
 import com.knacki.mimou.bridge.JsInterface;
-import com.knacki.mimou.R;
-import com.knacki.mimou.preference.PreferenceHolder;
+import com.knacki.mimou.bridge.MimouWebView;
+import com.knacki.mimou.preference.CredentialHolder;
 import com.knacki.mimou.preference.UserSettings;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.logging.Logger;
 
 public class MainActivity extends AppCompatActivity {
     public final static int SMS_PERMISSION_CALLBACK = 42;
-    protected WebView web;
+    protected MimouWebView web;
     protected JsInterface interfaceMimouDroid;
     protected MainActivityMenu menu;
     protected String currentChannel = null;
@@ -43,38 +41,19 @@ public class MainActivity extends AppCompatActivity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+
         setContentView(R.layout.activity_main);
         interfaceMimouDroid = new JsInterface();
-        web = (WebView) findViewById(R.id.webview);
-        web.setWebChromeClient(new WebChromeClient());
-        web.setWebViewClient(new WebViewClient() {
-            @Override
-            public boolean shouldOverrideUrlLoading(WebView view, String url) {
-                Uri uri = Uri.parse(url);
-
-                log.fine("Loading url " +url);
-                if (uri.getHost().equals(getString(R.string.mimouHost))) {
-                    List<String> pathSegments = uri.getPathSegments();
-                    if (pathSegments.size() > 0) {
-                        if (pathSegments.get(0).equals("login") && !url.contains("?phoneAccess=")) {
-                            PreferenceHolder.reset(MainActivity.this);
-                            showLogin();
-                            return true;
-                        }
-                    }
-                    return super.shouldOverrideUrlLoading(view, url);
-                }
-                startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
-                return true;
-            }
-        });
 
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
-            web.setWebContentsDebuggingEnabled(BuildConfig.DEBUG);
-        }
+        web = ((MimouWebView) findViewById(R.id.webview));
+        web.onContextCreated(this);
+
+        // Cookies stuff
+        android.webkit.CookieSyncManager.createInstance(this);
+        android.webkit.CookieManager.getInstance().setAcceptCookie(true);
+        CookieManager cookieJar = new CookieManager(null, java.net.CookiePolicy.ACCEPT_ALL);
+        java.net.CookieHandler.setDefault(cookieJar);
 
-        web.getSettings().setJavaScriptEnabled(true);
-        web.addJavascriptInterface(interfaceMimouDroid, "__native");
         needReload = true;
 
         Uri intentUri = getIntent().getData();
@@ -95,12 +74,16 @@ public class MainActivity extends AppCompatActivity {
         return true;
     }
 
+    public JsInterface getJsInterface() {
+        return interfaceMimouDroid;
+    }
+
     public void uiThread(Runnable e) {
         new Handler(Looper.getMainLooper()).post(e);
     }
 
     public void reload() {
-        if (needReload && web != null) {
+        if (needReload) {
             if (CredentialHolder.hasCredential(this)) {
                 final String url;
                 if (CredentialHolder.isLocal(this))
@@ -109,6 +92,7 @@ public class MainActivity extends AppCompatActivity {
                     url = getString(R.string.mimouUrl) + getString(R.string.loginUrl) + "/android?phoneAccess=" + CredentialHolder.getToken(this);
                 log.fine("Loading URL: " +url);
                 web.loadUrl(url);
+
             } else {
                 showLogin();
             }
@@ -140,26 +124,32 @@ public class MainActivity extends AppCompatActivity {
     @Override
     protected void onDestroy() {
         super.onDestroy();
+        web.onContextDestroyed();
+    }
 
-        if (web != null) {
-            web.removeAllViews();
-            web.clearHistory();
-            web.clearCache(true);
-            web.destroyDrawingCache();
-            web.pauseTimers();
-            web.destroy();
-            web = null;
-        }
+    public Map<String, List<String>> getCookies() {
+        Map<String, List<String>> result = new HashMap<>();
+        return result;
+    }
+
+    /**
+     * Unsafe (must be called from ui thread, web must be initialized)
+     */
+    private void loadJavascriptUnsafe(String js) {
+        log.severe(js);
+        web.loadUrl("javascript:" + js);
     }
 
     private void runJavascript(final String js) {
-        uiThread(new Runnable() {
+        web.onceLoaded(new MimouWebView.DoneLoadingListener() {
             @Override
-            public void run() {
-                if (web != null) {
-                    log.severe(js);
-                    web.loadUrl("javascript:" + js);
-                }
+            public void doneLoadind() {
+                uiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        loadJavascriptUnsafe(js);
+                    }
+                });
             }
         });
     }

+ 78 - 0
app/src/main/java/com/knacki/mimou/bridge/CookieManager.java

@@ -0,0 +1,78 @@
+package com.knacki.mimou.bridge;
+
+import java.io.IOException;
+import java.net.CookiePolicy;
+import java.net.CookieStore;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by thibal on 1/15/18.
+ */
+public class CookieManager extends java.net.CookieManager {
+    private android.webkit.CookieManager webkitCookieManager;
+
+    public CookieManager()
+    {
+        this(null, null);
+    }
+
+    public CookieManager(CookieStore store, CookiePolicy cookiePolicy)
+    {
+        super(null, cookiePolicy);
+
+        this.webkitCookieManager = android.webkit.CookieManager.getInstance();
+    }
+
+    @Override
+    public void put(URI uri, Map<String, List<String>> responseHeaders) throws IOException
+    {
+        // make sure our args are valid
+        if ((uri == null) || (responseHeaders == null)) return;
+
+        // save our url once
+        String url = uri.toString();
+
+        // go over the headers
+        for (String headerKey : responseHeaders.keySet())
+        {
+            // ignore headers which aren't cookie related
+            if ((headerKey == null) || !(headerKey.equalsIgnoreCase("Set-Cookie2") || headerKey.equalsIgnoreCase("Set-Cookie"))) continue;
+
+            // process each of the headers
+            for (String headerValue : responseHeaders.get(headerKey))
+            {
+                this.webkitCookieManager.setCookie(url, headerValue);
+            }
+        }
+    }
+
+    @Override
+    public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException
+    {
+        // make sure our args are valid
+        if ((uri == null) || (requestHeaders == null)) throw new IllegalArgumentException("Argument is null");
+
+        // save our url once
+        String url = uri.toString();
+
+        // prepare our response
+        Map<String, List<String>> res = new java.util.HashMap<String, List<String>>();
+
+        // get the cookie
+        String cookie = this.webkitCookieManager.getCookie(url);
+
+        // return it
+        if (cookie != null) res.put("Cookie", Arrays.asList(cookie));
+        return res;
+    }
+
+    @Override
+    public CookieStore getCookieStore()
+    {
+        // we don't want anyone to work with this cookie store directly
+        throw new UnsupportedOperationException();
+    }
+}

+ 1 - 8
app/src/main/java/com/knacki/mimou/bridge/JavascriptFunction.java

@@ -1,15 +1,8 @@
 package com.knacki.mimou.bridge;
 
-import com.knacki.mimou.sms.Sms;
-import com.knacki.mimou.sms.SmsReader;
-
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * Created by thibal on 1/5/18.
  */
-
 public class JavascriptFunction {
     private StringBuilder fncStr;
     private boolean firstArg = true;
@@ -25,7 +18,7 @@ public class JavascriptFunction {
     }
 
     private static String escapeStr(String s) {
-        return s.replaceAll("\"", "\\\\\"");
+        return s.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"");
     }
 
     public JavascriptFunction addArgument(String arg) {

+ 9 - 3
app/src/main/java/com/knacki/mimou/bridge/JsInterface.java

@@ -2,6 +2,7 @@ package com.knacki.mimou.bridge;
 
 import android.webkit.JavascriptInterface;
 
+import com.knacki.mimou.BuildConfig;
 import com.knacki.mimou.activity.MainActivity;
 import com.knacki.mimou.contact.Contact;
 import com.knacki.mimou.contact.ContactReader;
@@ -34,8 +35,8 @@ public class JsInterface {
     private final Logger log = Logger.getLogger(JsInterface.class.getName());
 
     public static final String TOGGLE_MENU = "toggleMenu";
-    public static final String ON_APPLICATION_PAUSED = "onApplicationPaused";
-    public static final String ON_APPLICATION_RESUMED = "onApplicationResumed";
+    public static final String ON_APPLICATION_PAUSED = "window.onApplicationPaused";
+    public static final String ON_APPLICATION_RESUMED = "window.onApplicationResumed";
     public static final String SET_CHANNEL_FAVORITE = "setChannelFavorite";
 
     MainActivity mainActivity;
@@ -44,6 +45,11 @@ public class JsInterface {
         this.mainActivity = mainActivity;
     }
 
+    @JavascriptInterface
+    public boolean isDebug() {
+        return BuildConfig.DEBUG;
+    }
+
     @JavascriptInterface
     public void logout() {
         CredentialHolder.reset(mainActivity);
@@ -108,7 +114,7 @@ public class JsInterface {
 
     @JavascriptInterface
     public void sendHttpRequest(String method, String url, int timeo, String expectedResponseType, String postPayload, final long callbackId) {
-        new XHRController(method, url).setTimeo(timeo).setResponseType(expectedResponseType).makeRequest(postPayload, new TypedCallback<XHRController.Response>() {
+        new XHRController(method, url).setTimeo(timeo).makeRequest(postPayload, new TypedCallback<XHRController.Response>() {
             @Override
             public void onResult(XHRController.Response result) {
                 mainActivity.runJavascript(new JavascriptFunction(callbackId).addArgument(result.statusCode).addArgument(result.statusText).addArgument(result.response));

+ 127 - 0
app/src/main/java/com/knacki/mimou/bridge/MimouWebView.java

@@ -0,0 +1,127 @@
+package com.knacki.mimou.bridge;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.webkit.WebChromeClient;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import com.knacki.mimou.BuildConfig;
+import com.knacki.mimou.R;
+import com.knacki.mimou.activity.MainActivity;
+import com.knacki.mimou.preference.PreferenceHolder;
+
+import java.util.ArrayDeque;
+import java.util.List;
+import java.util.logging.Logger;
+
+/**
+ * Created by thibal on 1/16/18.
+ */
+public class MimouWebView extends WebView {
+    private static final Logger log = Logger.getLogger(MimouWebView.class.getName());
+    protected boolean doneLoading;
+    protected MainActivity context;
+    protected ArrayDeque<DoneLoadingListener> doneLoadingListeners = new ArrayDeque<>();
+
+    public MimouWebView(Context context) {
+        super(context);
+    }
+
+    public MimouWebView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public MimouWebView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    public MimouWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public MimouWebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
+        super(context, attrs, defStyleAttr, privateBrowsing);
+    }
+
+    public void onContextCreated(final MainActivity context) {
+        setWebChromeClient(new WebChromeClient());
+        setWebViewClient(new MimouWebViewClient());
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            setWebContentsDebuggingEnabled(BuildConfig.DEBUG);
+        }
+
+        getSettings().setJavaScriptEnabled(true);
+        addJavascriptInterface(context.getJsInterface(), "__native");
+        this.context = context;
+    }
+
+    public void onContextDestroyed() {
+        removeAllViews();
+        clearHistory();
+        clearCache(true);
+        destroyDrawingCache();
+        pauseTimers();
+        destroy();
+    }
+
+    public void onceLoaded(DoneLoadingListener listener) {
+        if (doneLoading) {
+            listener.doneLoadind();
+        } else {
+            synchronized (doneLoadingListeners) {
+                doneLoadingListeners.add(listener);
+            }
+        }
+    }
+
+    public class MimouWebViewClient extends WebViewClient {
+        @Override
+        public boolean shouldOverrideUrlLoading(WebView view, String url) {
+            Uri uri = Uri.parse(url);
+
+            log.fine("Loading url " + url);
+            if (uri.getHost().equals(context.getString(R.string.mimouHost))) {
+                List<String> pathSegments = uri.getPathSegments();
+                if (pathSegments.size() > 0) {
+                    if (pathSegments.get(0).equals("login") && !url.contains("?phoneAccess=")) {
+                        PreferenceHolder.reset(context);
+                        context.showLogin();
+                        return true;
+                    }
+                }
+                return super.shouldOverrideUrlLoading(view, url);
+            }
+            context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
+            return true;
+        }
+
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            super.onPageStarted(view, url, favicon);
+            doneLoading = false;
+        }
+
+        @Override
+        public void onPageFinished(WebView view, String url) {
+            super.onPageFinished(view, url);
+            doneLoading = true;
+            synchronized (doneLoadingListeners) {
+                for (DoneLoadingListener l: doneLoadingListeners) {
+                    l.doneLoadind();
+                }
+                doneLoadingListeners.clear();
+            }
+        }
+    }
+
+    public interface DoneLoadingListener {
+        void doneLoadind();
+    }
+}

+ 40 - 30
app/src/main/java/com/knacki/mimou/bridge/XHRController.java

@@ -1,15 +1,11 @@
 package com.knacki.mimou.bridge;
 
 import java.io.BufferedInputStream;
-import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.net.HttpURLConnection;
 import java.net.URL;
-import java.nio.CharBuffer;
-import java.nio.charset.StandardCharsets;
 import java.security.InvalidParameterException;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -20,8 +16,7 @@ import java.util.logging.Logger;
 public class XHRController {
     public final Method method;
     public final String url;
-    protected int timeo = 5;
-    protected String responseType;
+    protected int timeo = 5000;
 
     private static final Logger log = Logger.getLogger(XHRController.class.getName());
 
@@ -35,30 +30,9 @@ public class XHRController {
         return this;
     }
 
-    public XHRController setResponseType(String respType) {
-        responseType = respType;
-        return this;
-    }
-
     public void makeRequest(String payload, JsInterface.TypedCallback<Response> callback) {
-        HttpURLConnection con = null;
-
-        Logger.getAnonymousLogger().severe("REQUEST " +this.url);
-        try {
-            con = (HttpURLConnection) (new URL(this.url).openConnection());
-            con.setDoOutput(true);
-            con.setRequestMethod(this.method.str);
-            if (payload != null)
-                con.getOutputStream().write(payload.getBytes());
-            InputStream in = new BufferedInputStream(con.getInputStream());
-            callback.onResult(readStream(con, in));
-        } catch (IOException e) {
-            log.log(Level.WARNING, "Cannot " +this.method.str +" " +this.url +": " +e.getMessage(), e);
-            callback.onResult(new Response(e));
-        } finally {
-            if (con != null)
-                con.disconnect();
-        }
+        Thread thread = new RequestRunner(payload, callback);
+        thread.start();
     }
 
     private Response readStream(HttpURLConnection con, InputStream stream) throws IOException {
@@ -71,7 +45,7 @@ public class XHRController {
             readCount = stream.read(byteRead);
             if (readCount > 0)
                 buffer.write(byteRead, 0, readCount);
-        } while (readCount == BUFFER_LEN);
+        } while (readCount > 0);
         return new Response((short) con.getResponseCode(), con.getResponseMessage(), buffer.toString("UTF-8"));
     }
 
@@ -138,4 +112,40 @@ public class XHRController {
             this.response = response;
         }
     }
+
+    private class RequestRunner extends Thread {
+        private final String payload;
+        private final JsInterface.TypedCallback<Response> callback;
+
+        RequestRunner(String payload, JsInterface.TypedCallback<Response> callback) {
+            this.payload = payload;
+            this.callback = callback;
+        }
+
+        @Override
+        public void run() {
+            HttpURLConnection con = null;
+            log.severe("REQUEST " +XHRController.this.url);
+
+            try {
+                URL url = new URL(XHRController.this.url);
+                con = (HttpURLConnection) (url.openConnection());
+                con.setDoOutput(true);
+                con.setConnectTimeout(1000);
+                con.setReadTimeout(timeo);
+                con.setRequestMethod(XHRController.this.method.str);
+
+                if (payload != null)
+                    con.getOutputStream().write(payload.getBytes());
+                InputStream in = new BufferedInputStream(con.getInputStream());
+                callback.onResult(readStream(con, in));
+            } catch (IOException e) {
+                log.log(Level.WARNING, "Cannot " +XHRController.this.method.str +" " +XHRController.this.url +": " +e.getMessage(), e);
+                callback.onResult(new Response(e));
+            } finally {
+                if (con != null)
+                    con.disconnect();
+            }
+        }
+    }
 }

+ 2 - 2
app/src/main/res/layout/activity_main.xml

@@ -9,12 +9,12 @@
     android:paddingRight="@dimen/activity_horizontal_margin"
     android:paddingTop="@dimen/activity_vertical_margin"
     tools:context="com.knacki.mimou.activity.MainActivity">
-    <WebView
+    <com.knacki.mimou.bridge.MimouWebView
         android:id="@+id/webview"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_marginRight="0px"
         android:layout_marginBottom="0px"
         android:layout_marginLeft="0px"
-        android:layout_marginTop="0px"></WebView>
+        android:layout_marginTop="0px"></com.knacki.mimou.bridge.MimouWebView>
 </RelativeLayout>