1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/base/WebappImpl.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,221 @@ 1.4 +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; 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; 1.10 + 1.11 +import android.content.Intent; 1.12 +import android.os.Bundle; 1.13 +import android.util.Log; 1.14 +import android.view.View; 1.15 +import android.view.MenuItem; 1.16 +import android.widget.TextView; 1.17 +import android.widget.RelativeLayout; 1.18 +import android.content.Context; 1.19 +import android.content.SharedPreferences; 1.20 +import android.graphics.Bitmap; 1.21 +import android.graphics.Color; 1.22 +import android.graphics.drawable.Drawable; 1.23 +import android.graphics.drawable.GradientDrawable; 1.24 +import android.view.animation.AnimationUtils; 1.25 +import android.view.animation.Animation; 1.26 +import android.widget.ImageView; 1.27 +import android.view.Display; 1.28 + 1.29 +import java.io.File; 1.30 +import java.net.URI; 1.31 + 1.32 +public class WebappImpl extends GeckoApp { 1.33 + private static final String LOGTAG = "GeckoWebappImpl"; 1.34 + 1.35 + private URI mOrigin; 1.36 + private TextView mTitlebarText = null; 1.37 + private View mTitlebar = null; 1.38 + 1.39 + private View mSplashscreen; 1.40 + 1.41 + protected int getIndex() { return 0; } 1.42 + 1.43 + @Override 1.44 + public int getLayout() { return R.layout.web_app; } 1.45 + 1.46 + @Override 1.47 + public boolean hasTabsSideBar() { return false; } 1.48 + 1.49 + @Override 1.50 + public void onCreate(Bundle savedInstanceState) 1.51 + { 1.52 + super.onCreate(savedInstanceState); 1.53 + 1.54 + mSplashscreen = (RelativeLayout) findViewById(R.id.splashscreen); 1.55 + if (!GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) { 1.56 + overridePendingTransition(R.anim.grow_fade_in_center, android.R.anim.fade_out); 1.57 + showSplash(); 1.58 + } 1.59 + 1.60 + String action = getIntent().getAction(); 1.61 + Bundle extras = getIntent().getExtras(); 1.62 + String title = extras != null ? extras.getString(Intent.EXTRA_SHORTCUT_NAME) : null; 1.63 + setTitle(title != null ? title : "Web App"); 1.64 + 1.65 + mTitlebarText = (TextView)findViewById(R.id.webapp_title); 1.66 + mTitlebar = findViewById(R.id.webapp_titlebar); 1.67 + if (!action.startsWith(ACTION_WEBAPP_PREFIX)) { 1.68 + Log.e(LOGTAG, "Webapp launch, but intent action is " + action + "!"); 1.69 + return; 1.70 + } 1.71 + 1.72 + // Try to use the origin stored in the WebappAllocator first 1.73 + String origin = WebappAllocator.getInstance(this).getAppForIndex(getIndex()); 1.74 + try { 1.75 + mOrigin = new URI(origin); 1.76 + } catch (java.net.URISyntaxException ex) { 1.77 + // If we can't parse the this is an app protocol, just settle for not having an origin 1.78 + if (!origin.startsWith("app://")) { 1.79 + return; 1.80 + } 1.81 + 1.82 + // If that failed fall back to the origin stored in the shortcut 1.83 + Log.i(LOGTAG, "Webapp is not registered with allocator"); 1.84 + try { 1.85 + mOrigin = new URI(getIntent().getData().toString()); 1.86 + } catch (java.net.URISyntaxException ex2) { 1.87 + Log.e(LOGTAG, "Unable to parse intent url: ", ex); 1.88 + } 1.89 + } 1.90 + } 1.91 + 1.92 + @Override 1.93 + protected void loadStartupTab(String uri) { 1.94 + String action = getIntent().getAction(); 1.95 + if (GeckoApp.ACTION_WEBAPP_PREFIX.equals(action)) { 1.96 + // This action assumes the uri is not an installed Webapp. We will 1.97 + // use the WebappAllocator to register the uri with an Android 1.98 + // process so it can run chromeless. 1.99 + int index = WebappAllocator.getInstance(this).findAndAllocateIndex(uri, "App", (Bitmap) null); 1.100 + Intent appIntent = GeckoAppShell.getWebappIntent(index, uri); 1.101 + startActivity(appIntent); 1.102 + finish(); 1.103 + } 1.104 + } 1.105 + 1.106 + private void showSplash() { 1.107 + SharedPreferences prefs = getSharedPreferences("webapps", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS); 1.108 + 1.109 + // get the favicon dominant color, stored when the app was installed 1.110 + int[] colors = new int[2]; 1.111 + int dominantColor = prefs.getInt(WebappAllocator.iconKey(getIndex()), -1); 1.112 + 1.113 + // now lighten it, to ensure that the icon stands out in the center 1.114 + float[] f = new float[3]; 1.115 + Color.colorToHSV(dominantColor, f); 1.116 + f[2] = Math.min(f[2]*2, 1.0f); 1.117 + colors[0] = Color.HSVToColor(255, f); 1.118 + 1.119 + // now generate a second, slightly darker version of the same color 1.120 + f[2] *= 0.75; 1.121 + colors[1] = Color.HSVToColor(255, f); 1.122 + 1.123 + // Draw the background gradient 1.124 + GradientDrawable gd = new GradientDrawable(GradientDrawable.Orientation.TL_BR, colors); 1.125 + gd.setGradientType(GradientDrawable.RADIAL_GRADIENT); 1.126 + Display display = getWindowManager().getDefaultDisplay(); 1.127 + gd.setGradientCenter(0.5f, 0.5f); 1.128 + gd.setGradientRadius(Math.max(display.getWidth()/2, display.getHeight()/2)); 1.129 + mSplashscreen.setBackgroundDrawable((Drawable)gd); 1.130 + 1.131 + // look for a logo.png in the profile dir and show it. If we can't find a logo show nothing 1.132 + File profile = getProfile().getDir(); 1.133 + File logoFile = new File(profile, "logo.png"); 1.134 + if (logoFile.exists()) { 1.135 + ImageView image = (ImageView)findViewById(R.id.splashscreen_icon); 1.136 + Drawable d = Drawable.createFromPath(logoFile.getPath()); 1.137 + image.setImageDrawable(d); 1.138 + 1.139 + Animation fadein = AnimationUtils.loadAnimation(this, R.anim.grow_fade_in_center); 1.140 + fadein.setStartOffset(500); 1.141 + fadein.setDuration(1000); 1.142 + image.startAnimation(fadein); 1.143 + } 1.144 + } 1.145 + 1.146 + @Override 1.147 + protected String getDefaultProfileName() { 1.148 + String action = getIntent().getAction(); 1.149 + if (!action.startsWith(ACTION_WEBAPP_PREFIX)) { 1.150 + Log.e(LOGTAG, "Webapp launch, but intent action is " + action + "!"); 1.151 + return null; 1.152 + } 1.153 + 1.154 + return "webapp" + action.substring(ACTION_WEBAPP_PREFIX.length()); 1.155 + } 1.156 + 1.157 + @Override 1.158 + protected boolean getSessionRestoreState(Bundle savedInstanceState) { 1.159 + // for now webapps never restore your session 1.160 + return false; 1.161 + } 1.162 + 1.163 + @Override 1.164 + public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) { 1.165 + switch(msg) { 1.166 + case SELECTED: 1.167 + case LOCATION_CHANGE: 1.168 + if (Tabs.getInstance().isSelectedTab(tab)) { 1.169 + final String urlString = tab.getURL(); 1.170 + final URI uri; 1.171 + 1.172 + try { 1.173 + uri = new URI(urlString); 1.174 + } catch (java.net.URISyntaxException ex) { 1.175 + mTitlebarText.setText(urlString); 1.176 + 1.177 + // If we can't parse the url, and its an app protocol hide 1.178 + // the titlebar and return, otherwise show the titlebar 1.179 + // and the full url 1.180 + if (!urlString.startsWith("app://")) { 1.181 + mTitlebar.setVisibility(View.VISIBLE); 1.182 + } else { 1.183 + mTitlebar.setVisibility(View.GONE); 1.184 + } 1.185 + return; 1.186 + } 1.187 + 1.188 + if (mOrigin != null && mOrigin.getHost().equals(uri.getHost())) { 1.189 + mTitlebar.setVisibility(View.GONE); 1.190 + } else { 1.191 + mTitlebarText.setText(uri.getScheme() + "://" + uri.getHost()); 1.192 + mTitlebar.setVisibility(View.VISIBLE); 1.193 + } 1.194 + } 1.195 + break; 1.196 + case LOADED: 1.197 + if (mSplashscreen != null && mSplashscreen.getVisibility() == View.VISIBLE) { 1.198 + Animation fadeout = AnimationUtils.loadAnimation(this, android.R.anim.fade_out); 1.199 + fadeout.setAnimationListener(new Animation.AnimationListener() { 1.200 + @Override 1.201 + public void onAnimationEnd(Animation animation) { 1.202 + mSplashscreen.setVisibility(View.GONE); 1.203 + } 1.204 + @Override 1.205 + public void onAnimationRepeat(Animation animation) { } 1.206 + @Override 1.207 + public void onAnimationStart(Animation animation) { } 1.208 + }); 1.209 + mSplashscreen.startAnimation(fadeout); 1.210 + } 1.211 + break; 1.212 + case START: 1.213 + if (mSplashscreen != null && mSplashscreen.getVisibility() == View.VISIBLE) { 1.214 + View area = findViewById(R.id.splashscreen_progress); 1.215 + area.setVisibility(View.VISIBLE); 1.216 + Animation fadein = AnimationUtils.loadAnimation(this, android.R.anim.fade_in); 1.217 + fadein.setDuration(1000); 1.218 + area.startAnimation(fadein); 1.219 + } 1.220 + break; 1.221 + } 1.222 + super.onTabChanged(tab, msg, data); 1.223 + } 1.224 +};