michael@0: /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko; michael@0: michael@0: import android.content.Intent; michael@0: import android.os.Bundle; michael@0: import android.util.Log; michael@0: import android.view.View; michael@0: import android.view.MenuItem; michael@0: import android.widget.TextView; michael@0: import android.widget.RelativeLayout; michael@0: import android.content.Context; michael@0: import android.content.SharedPreferences; michael@0: import android.graphics.Bitmap; michael@0: import android.graphics.Color; michael@0: import android.graphics.drawable.Drawable; michael@0: import android.graphics.drawable.GradientDrawable; michael@0: import android.view.animation.AnimationUtils; michael@0: import android.view.animation.Animation; michael@0: import android.widget.ImageView; michael@0: import android.view.Display; michael@0: michael@0: import java.io.File; michael@0: import java.net.URI; michael@0: michael@0: public class WebappImpl extends GeckoApp { michael@0: private static final String LOGTAG = "GeckoWebappImpl"; michael@0: michael@0: private URI mOrigin; michael@0: private TextView mTitlebarText = null; michael@0: private View mTitlebar = null; michael@0: michael@0: private View mSplashscreen; michael@0: michael@0: protected int getIndex() { return 0; } michael@0: michael@0: @Override michael@0: public int getLayout() { return R.layout.web_app; } michael@0: michael@0: @Override michael@0: public boolean hasTabsSideBar() { return false; } michael@0: michael@0: @Override michael@0: public void onCreate(Bundle savedInstanceState) michael@0: { michael@0: super.onCreate(savedInstanceState); michael@0: michael@0: mSplashscreen = (RelativeLayout) findViewById(R.id.splashscreen); michael@0: if (!GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) { michael@0: overridePendingTransition(R.anim.grow_fade_in_center, android.R.anim.fade_out); michael@0: showSplash(); michael@0: } michael@0: michael@0: String action = getIntent().getAction(); michael@0: Bundle extras = getIntent().getExtras(); michael@0: String title = extras != null ? extras.getString(Intent.EXTRA_SHORTCUT_NAME) : null; michael@0: setTitle(title != null ? title : "Web App"); michael@0: michael@0: mTitlebarText = (TextView)findViewById(R.id.webapp_title); michael@0: mTitlebar = findViewById(R.id.webapp_titlebar); michael@0: if (!action.startsWith(ACTION_WEBAPP_PREFIX)) { michael@0: Log.e(LOGTAG, "Webapp launch, but intent action is " + action + "!"); michael@0: return; michael@0: } michael@0: michael@0: // Try to use the origin stored in the WebappAllocator first michael@0: String origin = WebappAllocator.getInstance(this).getAppForIndex(getIndex()); michael@0: try { michael@0: mOrigin = new URI(origin); michael@0: } catch (java.net.URISyntaxException ex) { michael@0: // If we can't parse the this is an app protocol, just settle for not having an origin michael@0: if (!origin.startsWith("app://")) { michael@0: return; michael@0: } michael@0: michael@0: // If that failed fall back to the origin stored in the shortcut michael@0: Log.i(LOGTAG, "Webapp is not registered with allocator"); michael@0: try { michael@0: mOrigin = new URI(getIntent().getData().toString()); michael@0: } catch (java.net.URISyntaxException ex2) { michael@0: Log.e(LOGTAG, "Unable to parse intent url: ", ex); michael@0: } michael@0: } michael@0: } michael@0: michael@0: @Override michael@0: protected void loadStartupTab(String uri) { michael@0: String action = getIntent().getAction(); michael@0: if (GeckoApp.ACTION_WEBAPP_PREFIX.equals(action)) { michael@0: // This action assumes the uri is not an installed Webapp. We will michael@0: // use the WebappAllocator to register the uri with an Android michael@0: // process so it can run chromeless. michael@0: int index = WebappAllocator.getInstance(this).findAndAllocateIndex(uri, "App", (Bitmap) null); michael@0: Intent appIntent = GeckoAppShell.getWebappIntent(index, uri); michael@0: startActivity(appIntent); michael@0: finish(); michael@0: } michael@0: } michael@0: michael@0: private void showSplash() { michael@0: SharedPreferences prefs = getSharedPreferences("webapps", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS); michael@0: michael@0: // get the favicon dominant color, stored when the app was installed michael@0: int[] colors = new int[2]; michael@0: int dominantColor = prefs.getInt(WebappAllocator.iconKey(getIndex()), -1); michael@0: michael@0: // now lighten it, to ensure that the icon stands out in the center michael@0: float[] f = new float[3]; michael@0: Color.colorToHSV(dominantColor, f); michael@0: f[2] = Math.min(f[2]*2, 1.0f); michael@0: colors[0] = Color.HSVToColor(255, f); michael@0: michael@0: // now generate a second, slightly darker version of the same color michael@0: f[2] *= 0.75; michael@0: colors[1] = Color.HSVToColor(255, f); michael@0: michael@0: // Draw the background gradient michael@0: GradientDrawable gd = new GradientDrawable(GradientDrawable.Orientation.TL_BR, colors); michael@0: gd.setGradientType(GradientDrawable.RADIAL_GRADIENT); michael@0: Display display = getWindowManager().getDefaultDisplay(); michael@0: gd.setGradientCenter(0.5f, 0.5f); michael@0: gd.setGradientRadius(Math.max(display.getWidth()/2, display.getHeight()/2)); michael@0: mSplashscreen.setBackgroundDrawable((Drawable)gd); michael@0: michael@0: // look for a logo.png in the profile dir and show it. If we can't find a logo show nothing michael@0: File profile = getProfile().getDir(); michael@0: File logoFile = new File(profile, "logo.png"); michael@0: if (logoFile.exists()) { michael@0: ImageView image = (ImageView)findViewById(R.id.splashscreen_icon); michael@0: Drawable d = Drawable.createFromPath(logoFile.getPath()); michael@0: image.setImageDrawable(d); michael@0: michael@0: Animation fadein = AnimationUtils.loadAnimation(this, R.anim.grow_fade_in_center); michael@0: fadein.setStartOffset(500); michael@0: fadein.setDuration(1000); michael@0: image.startAnimation(fadein); michael@0: } michael@0: } michael@0: michael@0: @Override michael@0: protected String getDefaultProfileName() { michael@0: String action = getIntent().getAction(); michael@0: if (!action.startsWith(ACTION_WEBAPP_PREFIX)) { michael@0: Log.e(LOGTAG, "Webapp launch, but intent action is " + action + "!"); michael@0: return null; michael@0: } michael@0: michael@0: return "webapp" + action.substring(ACTION_WEBAPP_PREFIX.length()); michael@0: } michael@0: michael@0: @Override michael@0: protected boolean getSessionRestoreState(Bundle savedInstanceState) { michael@0: // for now webapps never restore your session michael@0: return false; michael@0: } michael@0: michael@0: @Override michael@0: public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) { michael@0: switch(msg) { michael@0: case SELECTED: michael@0: case LOCATION_CHANGE: michael@0: if (Tabs.getInstance().isSelectedTab(tab)) { michael@0: final String urlString = tab.getURL(); michael@0: final URI uri; michael@0: michael@0: try { michael@0: uri = new URI(urlString); michael@0: } catch (java.net.URISyntaxException ex) { michael@0: mTitlebarText.setText(urlString); michael@0: michael@0: // If we can't parse the url, and its an app protocol hide michael@0: // the titlebar and return, otherwise show the titlebar michael@0: // and the full url michael@0: if (!urlString.startsWith("app://")) { michael@0: mTitlebar.setVisibility(View.VISIBLE); michael@0: } else { michael@0: mTitlebar.setVisibility(View.GONE); michael@0: } michael@0: return; michael@0: } michael@0: michael@0: if (mOrigin != null && mOrigin.getHost().equals(uri.getHost())) { michael@0: mTitlebar.setVisibility(View.GONE); michael@0: } else { michael@0: mTitlebarText.setText(uri.getScheme() + "://" + uri.getHost()); michael@0: mTitlebar.setVisibility(View.VISIBLE); michael@0: } michael@0: } michael@0: break; michael@0: case LOADED: michael@0: if (mSplashscreen != null && mSplashscreen.getVisibility() == View.VISIBLE) { michael@0: Animation fadeout = AnimationUtils.loadAnimation(this, android.R.anim.fade_out); michael@0: fadeout.setAnimationListener(new Animation.AnimationListener() { michael@0: @Override michael@0: public void onAnimationEnd(Animation animation) { michael@0: mSplashscreen.setVisibility(View.GONE); michael@0: } michael@0: @Override michael@0: public void onAnimationRepeat(Animation animation) { } michael@0: @Override michael@0: public void onAnimationStart(Animation animation) { } michael@0: }); michael@0: mSplashscreen.startAnimation(fadeout); michael@0: } michael@0: break; michael@0: case START: michael@0: if (mSplashscreen != null && mSplashscreen.getVisibility() == View.VISIBLE) { michael@0: View area = findViewById(R.id.splashscreen_progress); michael@0: area.setVisibility(View.VISIBLE); michael@0: Animation fadein = AnimationUtils.loadAnimation(this, android.R.anim.fade_in); michael@0: fadein.setDuration(1000); michael@0: area.startAnimation(fadein); michael@0: } michael@0: break; michael@0: } michael@0: super.onTabChanged(tab, msg, data); michael@0: } michael@0: };