mobile/android/base/webapp/InstallHelper.java

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/base/webapp/InstallHelper.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,175 @@
     1.4 +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +package org.mozilla.gecko.webapp;
    1.10 +
    1.11 +import java.io.Closeable;
    1.12 +import java.io.File;
    1.13 +import java.io.FileOutputStream;
    1.14 +import java.io.IOException;
    1.15 +import java.io.InputStream;
    1.16 +import java.io.OutputStream;
    1.17 +
    1.18 +import org.json.JSONException;
    1.19 +import org.json.JSONObject;
    1.20 +import org.mozilla.gecko.GeckoAppShell;
    1.21 +import org.mozilla.gecko.GeckoEvent;
    1.22 +import org.mozilla.gecko.GeckoProfile;
    1.23 +import org.mozilla.gecko.gfx.BitmapUtils;
    1.24 +import org.mozilla.gecko.util.GeckoEventListener;
    1.25 +import org.mozilla.gecko.util.ThreadUtils;
    1.26 +
    1.27 +import android.content.Context;
    1.28 +import android.graphics.Bitmap;
    1.29 +import android.net.Uri;
    1.30 +import android.util.Log;
    1.31 +
    1.32 +public class InstallHelper implements GeckoEventListener {
    1.33 +    private static final String LOGTAG = "GeckoWebappInstallHelper";
    1.34 +    private static final String[] INSTALL_EVENT_NAMES = new String[] {"Webapps:Postinstall"};
    1.35 +    private final Context mContext;
    1.36 +    private final InstallCallback mCallback;
    1.37 +    private final ApkResources mApkResources;
    1.38 +
    1.39 +    public static interface InstallCallback {
    1.40 +        // on the GeckoThread
    1.41 +        void installCompleted(InstallHelper installHelper, String event, JSONObject message);
    1.42 +
    1.43 +        // on the GeckoBackgroundThread
    1.44 +        void installErrored(InstallHelper installHelper, Exception exception);
    1.45 +    }
    1.46 +
    1.47 +    public InstallHelper(Context context, ApkResources apkResources, InstallCallback cb) {
    1.48 +        mContext = context;
    1.49 +        mCallback = cb;
    1.50 +        mApkResources = apkResources;
    1.51 +    }
    1.52 +
    1.53 +    public void startInstall(String profileName) throws IOException {
    1.54 +        startInstall(profileName, null);
    1.55 +    }
    1.56 +
    1.57 +    public void startInstall(final String profileName, final JSONObject message) throws IOException {
    1.58 +        ThreadUtils.postToBackgroundThread(new Runnable() {
    1.59 +            @Override
    1.60 +            public void run() {
    1.61 +                try {
    1.62 +                    install(profileName, message);
    1.63 +                } catch (IOException e) {
    1.64 +                    handleException(e);
    1.65 +                }
    1.66 +            }
    1.67 +        });
    1.68 +    }
    1.69 +
    1.70 +    protected void handleException(Exception e) {
    1.71 +        if (mCallback != null) {
    1.72 +            mCallback.installErrored(this, e);
    1.73 +        } else {
    1.74 +            Log.e(LOGTAG, "mozApps.install failed", e);
    1.75 +        }
    1.76 +    }
    1.77 +
    1.78 +    private void install(String profileName, JSONObject message) throws IOException {
    1.79 +        if (message == null) {
    1.80 +            message = new JSONObject();
    1.81 +        }
    1.82 +
    1.83 +        // we can change the profile to be in the app's area here
    1.84 +        GeckoProfile profile = GeckoProfile.get(mContext, profileName);
    1.85 +
    1.86 +        try {
    1.87 +            message.put("apkPackageName", mApkResources.getPackageName());
    1.88 +            message.put("manifestURL", mApkResources.getManifestUrl());
    1.89 +            message.put("title", mApkResources.getAppName());
    1.90 +            message.put("manifest", new JSONObject(mApkResources.getManifest(mContext)));
    1.91 +
    1.92 +            String appType = mApkResources.getWebappType();
    1.93 +            message.putOpt("type", appType);
    1.94 +            if ("packaged".equals(appType)) {
    1.95 +                message.putOpt("updateManifest", new JSONObject(mApkResources.getMiniManifest(mContext)));
    1.96 +            }
    1.97 +
    1.98 +            message.putOpt("profilePath", profile.getDir());
    1.99 +
   1.100 +            if (mApkResources.isPackaged()) {
   1.101 +                File zipFile = copyApplicationZipFile();
   1.102 +                message.putOpt("zipFilePath", Uri.fromFile(zipFile).toString());
   1.103 +            }
   1.104 +        } catch (JSONException e) {
   1.105 +            handleException(e);
   1.106 +            return;
   1.107 +        }
   1.108 +
   1.109 +        registerGeckoListener();
   1.110 +
   1.111 +        GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Webapps:AutoInstall", message.toString()));
   1.112 +        calculateColor();
   1.113 +    }
   1.114 +
   1.115 +    public File copyApplicationZipFile() throws IOException {
   1.116 +        if (!mApkResources.isPackaged()) {
   1.117 +            return null;
   1.118 +        }
   1.119 +
   1.120 +        Uri uri = mApkResources.getZipFileUri();
   1.121 +
   1.122 +        InputStream in = null;
   1.123 +        OutputStream out = null;
   1.124 +        File destPath = new File(mApkResources.getFileDirectory(), "application.zip");
   1.125 +        try {
   1.126 +            in = mContext.getContentResolver().openInputStream(uri);
   1.127 +            out = new FileOutputStream(destPath);
   1.128 +            byte[] buffer = new byte[1024];
   1.129 +            int read = 0;
   1.130 +            while ((read = in.read(buffer)) != -1) {
   1.131 +                out.write(buffer, 0, read);
   1.132 +            }
   1.133 +            out.flush();
   1.134 +        } catch (IOException e) {
   1.135 +            throw e;
   1.136 +        } finally {
   1.137 +            close(in);
   1.138 +            close(out);
   1.139 +        }
   1.140 +        return destPath;
   1.141 +    }
   1.142 +
   1.143 +    private static void close(Closeable close) {
   1.144 +        if (close == null) {
   1.145 +            return;
   1.146 +        }
   1.147 +        try {
   1.148 +            close.close();
   1.149 +        } catch (IOException e) {
   1.150 +            // NOP
   1.151 +        }
   1.152 +    }
   1.153 +
   1.154 +    public void registerGeckoListener() {
   1.155 +        for (String eventName : INSTALL_EVENT_NAMES) {
   1.156 +            GeckoAppShell.registerEventListener(eventName, this);
   1.157 +        }
   1.158 +    }
   1.159 +
   1.160 +    private void calculateColor() {
   1.161 +        ThreadUtils.assertOnBackgroundThread();
   1.162 +        Allocator slots = Allocator.getInstance(mContext);
   1.163 +        int index = slots.getIndexForApp(mApkResources.getPackageName());
   1.164 +        Bitmap bitmap = BitmapUtils.getBitmapFromDrawable(mApkResources.getAppIcon());
   1.165 +        slots.updateColor(index, BitmapUtils.getDominantColor(bitmap));
   1.166 +    }
   1.167 +
   1.168 +    @Override
   1.169 +    public void handleMessage(String event, JSONObject message) {
   1.170 +        for (String eventName : INSTALL_EVENT_NAMES) {
   1.171 +            GeckoAppShell.unregisterEventListener(eventName, this);
   1.172 +        }
   1.173 +
   1.174 +        if (mCallback != null) {
   1.175 +            mCallback.installCompleted(this, event, message);
   1.176 +        }
   1.177 +    }
   1.178 +}

mercurial