зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1021342 - Eliminate non-synthetic web app code. r=myk,mfinkle
This commit is contained in:
Родитель
607b2c646c
Коммит
aa3662b743
14
configure.in
14
configure.in
|
@ -3941,7 +3941,6 @@ MOZ_USE_NATIVE_POPUP_WINDOWS=
|
|||
MOZ_ANDROID_HISTORY=
|
||||
MOZ_WEBSMS_BACKEND=
|
||||
MOZ_ANDROID_BEAM=
|
||||
MOZ_ANDROID_SYNTHAPKS=
|
||||
MOZ_LOCALE_SWITCHER=
|
||||
ACCESSIBILITY=1
|
||||
MOZ_TIME_MANAGER=
|
||||
|
@ -4966,18 +4965,6 @@ if test -n "$MOZ_ANDROID_BEAM"; then
|
|||
AC_DEFINE(MOZ_ANDROID_BEAM)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Synthesized Webapp APKs on Android
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(android-synthapks,
|
||||
[ --enable-android-synthapks Enable synthesized APKs],
|
||||
MOZ_ANDROID_SYNTHAPKS=1,
|
||||
MOZ_ANDROID_SYNTHAPKS=)
|
||||
|
||||
if test -n "$MOZ_ANDROID_SYNTHAPKS"; then
|
||||
AC_DEFINE(MOZ_ANDROID_SYNTHAPKS)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = JS Debugger XPCOM component (js/jsd)
|
||||
dnl ========================================================
|
||||
|
@ -8574,7 +8561,6 @@ AC_SUBST(MOZ_METRO)
|
|||
AC_SUBST(MOZ_ANDROID_HISTORY)
|
||||
AC_SUBST(MOZ_WEBSMS_BACKEND)
|
||||
AC_SUBST(MOZ_ANDROID_BEAM)
|
||||
AC_SUBST(MOZ_ANDROID_SYNTHAPKS)
|
||||
AC_SUBST(MOZ_LOCALE_SWITCHER)
|
||||
AC_SUBST(MOZ_DISABLE_GECKOVIEW)
|
||||
AC_SUBST(ENABLE_STRIP)
|
||||
|
|
|
@ -71,7 +71,7 @@ function _setAppProperties(aObj, aApp) {
|
|||
aObj.csp = aApp.csp;
|
||||
aObj.installOrigin = aApp.installOrigin;
|
||||
aObj.origin = aApp.origin;
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
aObj.apkPackageName = aApp.apkPackageName;
|
||||
#endif
|
||||
aObj.receipts = aApp.receipts ? JSON.parse(JSON.stringify(aApp.receipts)) : null;
|
||||
|
|
|
@ -1090,7 +1090,7 @@ this.DOMApplicationRegistry = {
|
|||
|
||||
switch (aMessage.name) {
|
||||
case "Webapps:Install": {
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
Services.obs.notifyObservers(mm, "webapps-runtime-install", JSON.stringify(msg));
|
||||
#else
|
||||
this.doInstall(msg, mm);
|
||||
|
@ -1119,7 +1119,7 @@ this.DOMApplicationRegistry = {
|
|||
this.doGetAll(msg, mm);
|
||||
break;
|
||||
case "Webapps:InstallPackage": {
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
Services.obs.notifyObservers(mm, "webapps-runtime-install-package", JSON.stringify(msg));
|
||||
#else
|
||||
this.doInstallPackage(msg, mm);
|
||||
|
@ -2510,15 +2510,15 @@ this.DOMApplicationRegistry = {
|
|||
} else if (manifest.package_path) {
|
||||
// If it is a local app then it must been installed from a local file
|
||||
// instead of web.
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
// In that case, we would already have the manifest, not just the update
|
||||
// manifest.
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
dontNeedNetwork = !!aData.app.manifest;
|
||||
#else
|
||||
if (aData.app.localInstallPath) {
|
||||
dontNeedNetwork = true;
|
||||
jsonManifest.package_path = "file://" + aData.app.localInstallPath;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// origin for install apps is meaningless here, since it's app:// and this
|
||||
|
|
|
@ -825,7 +825,6 @@ pref("browser.snippets.statsUrl", "https://snippets-stats.mozilla.org/mobile");
|
|||
pref("browser.snippets.enabled", true);
|
||||
pref("browser.snippets.syncPromo.enabled", true);
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
// The URL of the APK factory from which we obtain APKs for webapps.
|
||||
pref("browser.webapps.apkFactoryUrl", "https://controller.apk.firefox.com/application.apk");
|
||||
|
||||
|
@ -850,8 +849,6 @@ pref("browser.webapps.checkForUpdates", 1);
|
|||
// which is a test server that always reports all apps as having updates.
|
||||
pref("browser.webapps.updateCheckUrl", "https://controller.apk.firefox.com/app_updates");
|
||||
|
||||
#endif
|
||||
|
||||
// The mode of home provider syncing.
|
||||
// 0: Sync always
|
||||
// 1: Sync only when on wifi
|
||||
|
|
|
@ -188,7 +188,6 @@
|
|||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
<activity android:name="org.mozilla.gecko.webapp.Dispatcher"
|
||||
android:noHistory="true" >
|
||||
<intent-filter>
|
||||
|
@ -212,7 +211,6 @@
|
|||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
#endif
|
||||
|
||||
<activity android:name=".Webapp"
|
||||
android:label="@string/webapp_generic_name"
|
||||
|
|
|
@ -149,13 +149,6 @@ public class AppConstants {
|
|||
false;
|
||||
#endif
|
||||
|
||||
public static final boolean MOZ_ANDROID_SYNTHAPKS =
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
|
||||
// See this wiki page for more details about channel specific build defines:
|
||||
// https://wiki.mozilla.org/Platform/Channel-specific_build_defines
|
||||
public static final boolean RELEASE_BUILD =
|
||||
|
|
|
@ -793,41 +793,19 @@ public class GeckoAppShell
|
|||
public static Intent getWebappIntent(String aURI, String aOrigin, String aTitle, Bitmap aIcon) {
|
||||
Intent intent;
|
||||
|
||||
if (AppConstants.MOZ_ANDROID_SYNTHAPKS) {
|
||||
Allocator slots = Allocator.getInstance(getContext());
|
||||
int index = slots.getIndexForOrigin(aOrigin);
|
||||
Allocator slots = Allocator.getInstance(getContext());
|
||||
int index = slots.getIndexForOrigin(aOrigin);
|
||||
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
String packageName = slots.getAppForIndex(index);
|
||||
intent = getContext().getPackageManager().getLaunchIntentForPackage(packageName);
|
||||
if (aURI != null) {
|
||||
intent.setData(Uri.parse(aURI));
|
||||
}
|
||||
} else {
|
||||
int index;
|
||||
if (aIcon != null && !TextUtils.isEmpty(aTitle))
|
||||
index = WebappAllocator.getInstance(getContext()).findAndAllocateIndex(aOrigin, aTitle, aIcon);
|
||||
else
|
||||
index = WebappAllocator.getInstance(getContext()).getIndexForApp(aOrigin);
|
||||
|
||||
if (index == -1)
|
||||
return null;
|
||||
|
||||
intent = getWebappIntent(index, aURI);
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return intent;
|
||||
}
|
||||
String packageName = slots.getAppForIndex(index);
|
||||
intent = getContext().getPackageManager().getLaunchIntentForPackage(packageName);
|
||||
if (aURI != null) {
|
||||
intent.setData(Uri.parse(aURI));
|
||||
}
|
||||
|
||||
// The old implementation of getWebappIntent. Not used by MOZ_ANDROID_SYNTHAPKS.
|
||||
public static Intent getWebappIntent(int aIndex, String aURI) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(GeckoApp.ACTION_WEBAPP_PREFIX + aIndex);
|
||||
intent.setData(Uri.parse(aURI));
|
||||
intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
|
||||
AppConstants.ANDROID_PACKAGE_NAME + ".WebApps$WebApp" + aIndex);
|
||||
return intent;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,11 +6,7 @@
|
|||
#filter substitution
|
||||
package @ANDROID_PACKAGE_NAME@;
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
import org.mozilla.gecko.webapp.WebappImpl;
|
||||
#else
|
||||
import org.mozilla.gecko.WebappImpl;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This class serves only as a namespace wrapper for WebappImpl.
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class WebappAllocator {
|
||||
private final String LOGTAG = "GeckoWebappAllocator";
|
||||
// The number of Webapp# and WEBAPP# activites/apps/intents
|
||||
private final static int MAX_WEB_APPS = 100;
|
||||
|
||||
protected static WebappAllocator sInstance = null;
|
||||
public static WebappAllocator getInstance() {
|
||||
return getInstance(GeckoAppShell.getContext());
|
||||
}
|
||||
|
||||
public static synchronized WebappAllocator getInstance(Context cx) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new WebappAllocator(cx);
|
||||
}
|
||||
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
SharedPreferences mPrefs;
|
||||
|
||||
protected WebappAllocator(Context context) {
|
||||
mPrefs = context.getSharedPreferences("webapps", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
|
||||
}
|
||||
|
||||
public static String appKey(int index) {
|
||||
return "app" + index;
|
||||
}
|
||||
|
||||
static public String iconKey(int index) {
|
||||
return "icon" + index;
|
||||
}
|
||||
|
||||
public synchronized int findAndAllocateIndex(String app, String name, String aIconData) {
|
||||
Bitmap icon = (aIconData != null) ? BitmapUtils.getBitmapFromDataURI(aIconData) : null;
|
||||
return findAndAllocateIndex(app, name, icon);
|
||||
}
|
||||
|
||||
public synchronized int findAndAllocateIndex(final String app, final String name, final Bitmap aIcon) {
|
||||
int index = getIndexForApp(app);
|
||||
if (index != -1)
|
||||
return index;
|
||||
|
||||
for (int i = 0; i < MAX_WEB_APPS; ++i) {
|
||||
if (!mPrefs.contains(appKey(i))) {
|
||||
// found unused index i
|
||||
updateAppAllocation(app, i, aIcon);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// no more apps!
|
||||
return -1;
|
||||
}
|
||||
|
||||
public synchronized void updateAppAllocation(final String app,
|
||||
final int index,
|
||||
final Bitmap aIcon) {
|
||||
if (aIcon != null) {
|
||||
ThreadUtils.getBackgroundHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int color = 0;
|
||||
try {
|
||||
color = BitmapUtils.getDominantColor(aIcon);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Exception during getDominantColor", e);
|
||||
}
|
||||
mPrefs.edit()
|
||||
.putString(appKey(index), app)
|
||||
.putInt(iconKey(index), color).commit();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mPrefs.edit()
|
||||
.putString(appKey(index), app)
|
||||
.putInt(iconKey(index), 0).commit();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized int getIndexForApp(String app) {
|
||||
for (int i = 0; i < MAX_WEB_APPS; ++i) {
|
||||
if (mPrefs.getString(appKey(i), "").equals(app)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public synchronized String getAppForIndex(int index) {
|
||||
return mPrefs.getString(appKey(index), null);
|
||||
}
|
||||
|
||||
public synchronized int releaseIndexForApp(String app) {
|
||||
int index = getIndexForApp(app);
|
||||
if (index == -1)
|
||||
return -1;
|
||||
|
||||
releaseIndex(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
public synchronized void releaseIndex(final int index) {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mPrefs.edit()
|
||||
.remove(appKey(index))
|
||||
.remove(iconKey(index))
|
||||
.commit();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,221 +0,0 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.TextView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Animation;
|
||||
import android.widget.ImageView;
|
||||
import android.view.Display;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
||||
public class WebappImpl extends GeckoApp {
|
||||
private static final String LOGTAG = "GeckoWebappImpl";
|
||||
|
||||
private URI mOrigin;
|
||||
private TextView mTitlebarText = null;
|
||||
private View mTitlebar = null;
|
||||
|
||||
private View mSplashscreen;
|
||||
|
||||
protected int getIndex() { return 0; }
|
||||
|
||||
@Override
|
||||
public int getLayout() { return R.layout.web_app; }
|
||||
|
||||
@Override
|
||||
public boolean hasTabsSideBar() { return false; }
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mSplashscreen = (RelativeLayout) findViewById(R.id.splashscreen);
|
||||
if (!GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) {
|
||||
overridePendingTransition(R.anim.grow_fade_in_center, android.R.anim.fade_out);
|
||||
showSplash();
|
||||
}
|
||||
|
||||
String action = getIntent().getAction();
|
||||
Bundle extras = getIntent().getExtras();
|
||||
String title = extras != null ? extras.getString(Intent.EXTRA_SHORTCUT_NAME) : null;
|
||||
setTitle(title != null ? title : "Web App");
|
||||
|
||||
mTitlebarText = (TextView)findViewById(R.id.webapp_title);
|
||||
mTitlebar = findViewById(R.id.webapp_titlebar);
|
||||
if (!action.startsWith(ACTION_WEBAPP_PREFIX)) {
|
||||
Log.e(LOGTAG, "Webapp launch, but intent action is " + action + "!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to use the origin stored in the WebappAllocator first
|
||||
String origin = WebappAllocator.getInstance(this).getAppForIndex(getIndex());
|
||||
try {
|
||||
mOrigin = new URI(origin);
|
||||
} catch (java.net.URISyntaxException ex) {
|
||||
// If we can't parse the this is an app protocol, just settle for not having an origin
|
||||
if (!origin.startsWith("app://")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If that failed fall back to the origin stored in the shortcut
|
||||
Log.i(LOGTAG, "Webapp is not registered with allocator");
|
||||
try {
|
||||
mOrigin = new URI(getIntent().getData().toString());
|
||||
} catch (java.net.URISyntaxException ex2) {
|
||||
Log.e(LOGTAG, "Unable to parse intent url: ", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadStartupTab(String uri) {
|
||||
String action = getIntent().getAction();
|
||||
if (GeckoApp.ACTION_WEBAPP_PREFIX.equals(action)) {
|
||||
// This action assumes the uri is not an installed Webapp. We will
|
||||
// use the WebappAllocator to register the uri with an Android
|
||||
// process so it can run chromeless.
|
||||
int index = WebappAllocator.getInstance(this).findAndAllocateIndex(uri, "App", (Bitmap) null);
|
||||
Intent appIntent = GeckoAppShell.getWebappIntent(index, uri);
|
||||
startActivity(appIntent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void showSplash() {
|
||||
SharedPreferences prefs = getSharedPreferences("webapps", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
|
||||
|
||||
// get the favicon dominant color, stored when the app was installed
|
||||
int[] colors = new int[2];
|
||||
int dominantColor = prefs.getInt(WebappAllocator.iconKey(getIndex()), -1);
|
||||
|
||||
// now lighten it, to ensure that the icon stands out in the center
|
||||
float[] f = new float[3];
|
||||
Color.colorToHSV(dominantColor, f);
|
||||
f[2] = Math.min(f[2]*2, 1.0f);
|
||||
colors[0] = Color.HSVToColor(255, f);
|
||||
|
||||
// now generate a second, slightly darker version of the same color
|
||||
f[2] *= 0.75;
|
||||
colors[1] = Color.HSVToColor(255, f);
|
||||
|
||||
// Draw the background gradient
|
||||
GradientDrawable gd = new GradientDrawable(GradientDrawable.Orientation.TL_BR, colors);
|
||||
gd.setGradientType(GradientDrawable.RADIAL_GRADIENT);
|
||||
Display display = getWindowManager().getDefaultDisplay();
|
||||
gd.setGradientCenter(0.5f, 0.5f);
|
||||
gd.setGradientRadius(Math.max(display.getWidth()/2, display.getHeight()/2));
|
||||
mSplashscreen.setBackgroundDrawable((Drawable)gd);
|
||||
|
||||
// look for a logo.png in the profile dir and show it. If we can't find a logo show nothing
|
||||
File profile = getProfile().getDir();
|
||||
File logoFile = new File(profile, "logo.png");
|
||||
if (logoFile.exists()) {
|
||||
ImageView image = (ImageView)findViewById(R.id.splashscreen_icon);
|
||||
Drawable d = Drawable.createFromPath(logoFile.getPath());
|
||||
image.setImageDrawable(d);
|
||||
|
||||
Animation fadein = AnimationUtils.loadAnimation(this, R.anim.grow_fade_in_center);
|
||||
fadein.setStartOffset(500);
|
||||
fadein.setDuration(1000);
|
||||
image.startAnimation(fadein);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultProfileName() {
|
||||
String action = getIntent().getAction();
|
||||
if (!action.startsWith(ACTION_WEBAPP_PREFIX)) {
|
||||
Log.e(LOGTAG, "Webapp launch, but intent action is " + action + "!");
|
||||
return null;
|
||||
}
|
||||
|
||||
return "webapp" + action.substring(ACTION_WEBAPP_PREFIX.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getSessionRestoreState(Bundle savedInstanceState) {
|
||||
// for now webapps never restore your session
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) {
|
||||
switch(msg) {
|
||||
case SELECTED:
|
||||
case LOCATION_CHANGE:
|
||||
if (Tabs.getInstance().isSelectedTab(tab)) {
|
||||
final String urlString = tab.getURL();
|
||||
final URI uri;
|
||||
|
||||
try {
|
||||
uri = new URI(urlString);
|
||||
} catch (java.net.URISyntaxException ex) {
|
||||
mTitlebarText.setText(urlString);
|
||||
|
||||
// If we can't parse the url, and its an app protocol hide
|
||||
// the titlebar and return, otherwise show the titlebar
|
||||
// and the full url
|
||||
if (!urlString.startsWith("app://")) {
|
||||
mTitlebar.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mTitlebar.setVisibility(View.GONE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mOrigin != null && mOrigin.getHost().equals(uri.getHost())) {
|
||||
mTitlebar.setVisibility(View.GONE);
|
||||
} else {
|
||||
mTitlebarText.setText(uri.getScheme() + "://" + uri.getHost());
|
||||
mTitlebar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LOADED:
|
||||
if (mSplashscreen != null && mSplashscreen.getVisibility() == View.VISIBLE) {
|
||||
Animation fadeout = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
|
||||
fadeout.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
mSplashscreen.setVisibility(View.GONE);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) { }
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) { }
|
||||
});
|
||||
mSplashscreen.startAnimation(fadeout);
|
||||
}
|
||||
break;
|
||||
case START:
|
||||
if (mSplashscreen != null && mSplashscreen.getVisibility() == View.VISIBLE) {
|
||||
View area = findViewById(R.id.splashscreen_progress);
|
||||
area.setVisibility(View.VISIBLE);
|
||||
Animation fadein = AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
|
||||
fadein.setDuration(1000);
|
||||
area.startAnimation(fadein);
|
||||
}
|
||||
break;
|
||||
}
|
||||
super.onTabChanged(tab, msg, data);
|
||||
}
|
||||
};
|
|
@ -4,19 +4,6 @@
|
|||
android:windowSoftInputMode="stateUnspecified|adjustResize"
|
||||
android:process=":@ANDROID_PACKAGE_NAME@.Webapp@APPNUM@"
|
||||
android:theme="@style/Gecko.App"
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
android:launchMode="singleTop"
|
||||
android:exported="true"
|
||||
/>
|
||||
#else
|
||||
android:launchMode="singleTask"
|
||||
android:taskAffinity="org.mozilla.gecko.WEBAPP@APPNUM@"
|
||||
android:excludeFromRecents="true">
|
||||
<intent-filter>
|
||||
<action android:name="org.mozilla.gecko.WEBAPP@APPNUM@" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="org.mozilla.gecko.ACTION_ALERT_CALLBACK" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
#endif
|
||||
|
|
|
@ -404,8 +404,6 @@ gbjar.sources += [
|
|||
'webapp/TaskKiller.java',
|
||||
'webapp/UninstallListener.java',
|
||||
'webapp/WebappImpl.java',
|
||||
'WebappAllocator.java',
|
||||
'WebappImpl.java',
|
||||
'widget/ActivityChooserModel.java',
|
||||
'widget/AllCapsTextView.java',
|
||||
'widget/AnimatedHeightLayout.java',
|
||||
|
|
|
@ -5,33 +5,6 @@
|
|||
|
||||
package org.mozilla.gecko.webapp;
|
||||
|
||||
import org.mozilla.gecko.ActivityHandlerHelper;
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.GeckoProfile;
|
||||
import org.mozilla.gecko.favicons.decoders.FaviconDecoder;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.util.ActivityResultHandler;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.WebappAllocator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
@ -40,6 +13,25 @@ import java.util.Set;
|
|||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.ActivityHandlerHelper;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoProfile;
|
||||
import org.mozilla.gecko.util.ActivityResultHandler;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
public class EventListener implements NativeEventListener {
|
||||
|
||||
|
@ -68,18 +60,10 @@ public class EventListener implements NativeEventListener {
|
|||
@Override
|
||||
public void handleMessage(String event, NativeJSObject message, EventCallback callback) {
|
||||
try {
|
||||
if (AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("Webapps:InstallApk")) {
|
||||
if (event.equals("Webapps:InstallApk")) {
|
||||
installApk(GeckoAppShell.getGeckoInterface().getActivity(), message, callback);
|
||||
} else if (event.equals("Webapps:Postinstall")) {
|
||||
if (AppConstants.MOZ_ANDROID_SYNTHAPKS) {
|
||||
postInstallWebapp(message.getString("apkPackageName"), message.getString("origin"));
|
||||
} else {
|
||||
postInstallWebapp(message.getString("name"),
|
||||
message.getString("manifestURL"),
|
||||
message.getString("origin"),
|
||||
message.getString("iconURL"),
|
||||
message.getString("originalOrigin"));
|
||||
}
|
||||
postInstallWebapp(message.getString("apkPackageName"), message.getString("origin"));
|
||||
} else if (event.equals("Webapps:Open")) {
|
||||
Intent intent = GeckoAppShell.getWebappIntent(message.getString("manifestURL"),
|
||||
message.getString("origin"),
|
||||
|
@ -88,16 +72,6 @@ public class EventListener implements NativeEventListener {
|
|||
return;
|
||||
}
|
||||
GeckoAppShell.getGeckoInterface().getActivity().startActivity(intent);
|
||||
} else if (!AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("Webapps:Uninstall")) {
|
||||
uninstallWebapp(message.getString("origin"));
|
||||
} else if (!AppConstants.MOZ_ANDROID_SYNTHAPKS && event.equals("Webapps:Preinstall")) {
|
||||
String name = message.getString("name");
|
||||
String manifestURL = message.getString("manifestURL");
|
||||
String origin = message.getString("origin");
|
||||
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("profile", preInstallWebapp(name, manifestURL, origin).toString());
|
||||
callback.sendSuccess(obj);
|
||||
} else if (event.equals("Webapps:GetApkVersions")) {
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("versions", getApkVersions(GeckoAppShell.getGeckoInterface().getActivity(),
|
||||
|
@ -109,30 +83,6 @@ public class EventListener implements NativeEventListener {
|
|||
}
|
||||
}
|
||||
|
||||
// Not used by MOZ_ANDROID_SYNTHAPKS.
|
||||
public static File preInstallWebapp(String aTitle, String aURI, String aOrigin) {
|
||||
int index = WebappAllocator.getInstance(GeckoAppShell.getContext()).findAndAllocateIndex(aOrigin, aTitle, (String) null);
|
||||
GeckoProfile profile = GeckoProfile.get(GeckoAppShell.getContext(), "webapp" + index);
|
||||
return profile.getDir();
|
||||
}
|
||||
|
||||
// Not used by MOZ_ANDROID_SYNTHAPKS.
|
||||
public static void postInstallWebapp(String aTitle, String aURI, String aOrigin, String aIconURL, String aOriginalOrigin) {
|
||||
WebappAllocator allocator = WebappAllocator.getInstance(GeckoAppShell.getContext());
|
||||
int index = allocator.getIndexForApp(aOriginalOrigin);
|
||||
|
||||
assert aIconURL != null;
|
||||
|
||||
final int preferredSize = GeckoAppShell.getPreferredIconSize();
|
||||
Bitmap icon = FaviconDecoder.getMostSuitableBitmapFromDataURI(aIconURL, preferredSize);
|
||||
|
||||
assert aOrigin != null && index != -1;
|
||||
allocator.updateAppAllocation(aOrigin, index, icon);
|
||||
|
||||
GeckoAppShell.createShortcut(aTitle, aURI, aOrigin, icon, "webapp");
|
||||
}
|
||||
|
||||
// Used by MOZ_ANDROID_SYNTHAPKS.
|
||||
public static void postInstallWebapp(String aPackageName, String aOrigin) {
|
||||
Allocator allocator = Allocator.getInstance(GeckoAppShell.getContext());
|
||||
int index = allocator.findOrAllocatePackage(aPackageName);
|
||||
|
|
|
@ -147,9 +147,7 @@ public class UninstallListener extends BroadcastReceiver {
|
|||
ThreadUtils.assertOnBackgroundThread();
|
||||
|
||||
// Perform webapp uninstalls as appropiate.
|
||||
if (AppConstants.MOZ_ANDROID_SYNTHAPKS) {
|
||||
UninstallListener.initUninstallPackageScan(mApp.getApplicationContext());
|
||||
}
|
||||
UninstallListener.initUninstallPackageScan(mApp.getApplicationContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,11 +11,9 @@ Cu.import("resource://gre/modules/NetUtil.jsm");
|
|||
Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
|
||||
Cu.import("resource://gre/modules/PermissionPromptHelper.jsm");
|
||||
Cu.import("resource://gre/modules/ContactService.jsm");
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Notifications", "resource://gre/modules/Notifications.jsm");
|
||||
#endif
|
||||
|
||||
function pref(name, value) {
|
||||
return {
|
||||
|
@ -70,14 +68,12 @@ let WebappRT = {
|
|||
});
|
||||
}
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
// If the app is in debug mode, configure and enable the remote debugger.
|
||||
sendMessageToJava({ type: "NativeApp:IsDebuggable" }, (response) => {
|
||||
if (response.isDebuggable) {
|
||||
this._enableRemoteDebugger(aUrl);
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
this.findManifestUrlFor(aUrl, aCallback);
|
||||
},
|
||||
|
@ -163,7 +159,6 @@ let WebappRT = {
|
|||
}
|
||||
},
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
_enableRemoteDebugger: function(aUrl) {
|
||||
// Skip the connection prompt in favor of notifying the user below.
|
||||
Services.prefs.setBoolPref("devtools.debugger.prompt-connection", false);
|
||||
|
@ -195,7 +190,6 @@ let WebappRT = {
|
|||
});
|
||||
});
|
||||
},
|
||||
#endif
|
||||
|
||||
handleEvent: function(event) {
|
||||
let target = event.target;
|
||||
|
|
|
@ -12,9 +12,7 @@ Cu.import("resource://gre/modules/Services.jsm")
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebappManager", "resource://gre/modules/WebappManager.jsm");
|
||||
#endif
|
||||
|
||||
const DEFAULT_ICON = "chrome://browser/skin/images/default-app-icon.png";
|
||||
|
||||
|
@ -45,51 +43,9 @@ function openLink(aEvent) {
|
|||
} catch (ex) {}
|
||||
}
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
function checkForUpdates(aEvent) {
|
||||
WebappManager.checkForUpdates(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef MOZ_ANDROID_SYNTHAPKS
|
||||
var ContextMenus = {
|
||||
target: null,
|
||||
|
||||
init: function() {
|
||||
document.addEventListener("contextmenu", this, false);
|
||||
document.getElementById("addToHomescreenLabel").addEventListener("click", this.addToHomescreen, false);
|
||||
document.getElementById("uninstallLabel").addEventListener("click", this.uninstall, false);
|
||||
},
|
||||
|
||||
handleEvent: function(event) {
|
||||
// store the target of context menu events so that we know which app to act on
|
||||
this.target = event.target;
|
||||
while (!this.target.hasAttribute("contextmenu")) {
|
||||
this.target = this.target.parentNode;
|
||||
}
|
||||
},
|
||||
|
||||
addToHomescreen: function() {
|
||||
let manifest = this.target.manifest;
|
||||
gChromeWin.WebappsUI.createShortcut(manifest.name, manifest.fullLaunchPath(), manifest.biggestIconURL || DEFAULT_ICON, "webapp");
|
||||
this.target = null;
|
||||
},
|
||||
|
||||
uninstall: function() {
|
||||
navigator.mozApps.mgmt.uninstall(this.target.app);
|
||||
|
||||
let manifest = this.target.manifest;
|
||||
gChromeWin.sendMessageToJava({
|
||||
type: "Shortcut:Remove",
|
||||
title: manifest.name,
|
||||
url: manifest.fullLaunchPath(),
|
||||
origin: this.target.app.origin,
|
||||
shortcutType: "webapp"
|
||||
});
|
||||
this.target = null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
function onLoad(aEvent) {
|
||||
let elmts = document.querySelectorAll("[pref]");
|
||||
|
@ -97,17 +53,11 @@ function onLoad(aEvent) {
|
|||
elmts[i].addEventListener("click", openLink, false);
|
||||
}
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
document.getElementById("update-item").addEventListener("click", checkForUpdates, false);
|
||||
#endif
|
||||
|
||||
navigator.mozApps.mgmt.oninstall = onInstall;
|
||||
navigator.mozApps.mgmt.onuninstall = onUninstall;
|
||||
updateList();
|
||||
|
||||
#ifndef MOZ_ANDROID_SYNTHAPKS
|
||||
ContextMenus.init();
|
||||
#endif
|
||||
}
|
||||
|
||||
function updateList() {
|
||||
|
@ -131,9 +81,6 @@ function addApplication(aApp) {
|
|||
|
||||
let container = document.createElement("div");
|
||||
container.className = "app list-item";
|
||||
#ifndef MOZ_ANDROID_SYNTHAPKS
|
||||
container.setAttribute("contextmenu", "appmenu");
|
||||
#endif
|
||||
container.setAttribute("id", "app-" + aApp.origin);
|
||||
container.setAttribute("mozApp", aApp.origin);
|
||||
container.setAttribute("title", manifest.name);
|
||||
|
|
|
@ -28,14 +28,6 @@
|
|||
</head>
|
||||
|
||||
<body dir="&locale.dir;">
|
||||
|
||||
#ifndef MOZ_ANDROID_SYNTHAPKS
|
||||
<menu type="context" id="appmenu">
|
||||
<menuitem id="addToHomescreenLabel" label="&aboutApps.addToHomescreen;"></menuitem>
|
||||
<menuitem id="uninstallLabel" label="&aboutApps.uninstall;"></menuitem>
|
||||
</menu>
|
||||
#endif
|
||||
|
||||
<div class="header">
|
||||
<div>&aboutApps.header;</div>
|
||||
<div id="header-button" role="button" aria-label="&aboutApps.browseMarketplace;" pref="app.marketplaceURL"/>
|
||||
|
@ -55,13 +47,11 @@
|
|||
<div id="browse-title" class="title">&aboutApps.browseMarketplace;</div>
|
||||
</div>
|
||||
</div>
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
<div class="list-item" id="update-item" role="button">
|
||||
<img class="icon" src="chrome://browser/skin/images/update.png" />
|
||||
<div class="inner">
|
||||
<div id="browse-title" class="title">&aboutApps.checkForUpdates;</div>
|
||||
</div>
|
||||
</div>
|
||||
#endif
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -77,10 +77,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "ShumwayUtils",
|
|||
"resource://shumway/ShumwayUtils.jsm");
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "WebappManager",
|
||||
"resource://gre/modules/WebappManager.jsm");
|
||||
#endif
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
|
||||
"resource://gre/modules/CharsetMenu.jsm");
|
||||
|
@ -326,7 +324,6 @@ var BrowserApp = {
|
|||
Services.obs.addObserver(this, "FormHistory:Init", false);
|
||||
Services.obs.addObserver(this, "gather-telemetry", false);
|
||||
Services.obs.addObserver(this, "keyword-search", false);
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
Services.obs.addObserver(this, "webapps-runtime-install", false);
|
||||
Services.obs.addObserver(this, "webapps-runtime-install-package", false);
|
||||
Services.obs.addObserver(this, "webapps-ask-install", false);
|
||||
|
@ -335,7 +332,6 @@ var BrowserApp = {
|
|||
Services.obs.addObserver(this, "Webapps:AutoInstall", false);
|
||||
Services.obs.addObserver(this, "Webapps:Load", false);
|
||||
Services.obs.addObserver(this, "Webapps:AutoUninstall", false);
|
||||
#endif
|
||||
Services.obs.addObserver(this, "sessionstore-state-purge-complete", false);
|
||||
|
||||
function showFullScreenWarning() {
|
||||
|
@ -377,13 +373,9 @@ var BrowserApp = {
|
|||
XPInstallObserver.init();
|
||||
CharacterEncoding.init();
|
||||
ActivityObserver.init();
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
// TODO: replace with Android implementation of WebappOSUtils.isLaunchable.
|
||||
Cu.import("resource://gre/modules/Webapps.jsm");
|
||||
DOMApplicationRegistry.allAppsLaunchable = true;
|
||||
#else
|
||||
WebappsUI.init();
|
||||
#endif
|
||||
RemoteDebugger.init();
|
||||
Reader.init();
|
||||
UserAgentOverrides.init();
|
||||
|
@ -770,9 +762,6 @@ var BrowserApp = {
|
|||
HealthReportStatusListener.uninit();
|
||||
CharacterEncoding.uninit();
|
||||
SearchEngines.uninit();
|
||||
#ifndef MOZ_ANDROID_SYNTHAPKS
|
||||
WebappsUI.uninit();
|
||||
#endif
|
||||
RemoteDebugger.uninit();
|
||||
Reader.uninit();
|
||||
UserAgentOverrides.uninit();
|
||||
|
@ -961,7 +950,6 @@ var BrowserApp = {
|
|||
sendMessageToJava(message);
|
||||
},
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
_loadWebapp: function(aMessage) {
|
||||
|
||||
this._initRuntime(this._startupStatus, aMessage.url, aUrl => {
|
||||
|
@ -969,7 +957,6 @@ var BrowserApp = {
|
|||
this.addTab(aUrl, { title: aMessage.name });
|
||||
});
|
||||
},
|
||||
#endif
|
||||
|
||||
// Calling this will update the state in BrowserApp after a tab has been
|
||||
// closed in the Java UI.
|
||||
|
@ -1627,7 +1614,6 @@ var BrowserApp = {
|
|||
this.notifyPrefObservers(aData);
|
||||
break;
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
case "webapps-runtime-install":
|
||||
WebappManager.install(JSON.parse(aData), aSubject);
|
||||
break;
|
||||
|
@ -1661,7 +1647,6 @@ var BrowserApp = {
|
|||
case "Webapps:AutoUninstall":
|
||||
WebappManager.autoUninstall(JSON.parse(aData));
|
||||
break;
|
||||
#endif
|
||||
|
||||
case "Locale:Changed":
|
||||
if (aData) {
|
||||
|
@ -7034,246 +7019,6 @@ var ActivityObserver = {
|
|||
}
|
||||
};
|
||||
|
||||
#ifndef MOZ_ANDROID_SYNTHAPKS
|
||||
var WebappsUI = {
|
||||
init: function init() {
|
||||
Cu.import("resource://gre/modules/Webapps.jsm");
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
DOMApplicationRegistry.allAppsLaunchable = true;
|
||||
|
||||
Services.obs.addObserver(this, "webapps-ask-install", false);
|
||||
Services.obs.addObserver(this, "webapps-launch", false);
|
||||
Services.obs.addObserver(this, "webapps-uninstall", false);
|
||||
Services.obs.addObserver(this, "webapps-install-error", false);
|
||||
},
|
||||
|
||||
uninit: function unint() {
|
||||
Services.obs.removeObserver(this, "webapps-ask-install");
|
||||
Services.obs.removeObserver(this, "webapps-launch");
|
||||
Services.obs.removeObserver(this, "webapps-uninstall");
|
||||
Services.obs.removeObserver(this, "webapps-install-error");
|
||||
},
|
||||
|
||||
DEFAULT_ICON: "chrome://browser/skin/images/default-app-icon.png",
|
||||
DEFAULT_PREFS_FILENAME: "default-prefs.js",
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
let data = {};
|
||||
try {
|
||||
data = JSON.parse(aData);
|
||||
data.mm = aSubject;
|
||||
} catch(ex) { }
|
||||
switch (aTopic) {
|
||||
case "webapps-install-error":
|
||||
let msg = "";
|
||||
switch (aData) {
|
||||
case "INVALID_MANIFEST":
|
||||
case "MANIFEST_PARSE_ERROR":
|
||||
msg = Strings.browser.GetStringFromName("webapps.manifestInstallError");
|
||||
break;
|
||||
case "NETWORK_ERROR":
|
||||
case "MANIFEST_URL_ERROR":
|
||||
msg = Strings.browser.GetStringFromName("webapps.networkInstallError");
|
||||
break;
|
||||
default:
|
||||
msg = Strings.browser.GetStringFromName("webapps.installError");
|
||||
}
|
||||
NativeWindow.toast.show(msg, "short");
|
||||
console.log("Error installing app: " + aData);
|
||||
break;
|
||||
case "webapps-ask-install":
|
||||
this.doInstall(data);
|
||||
break;
|
||||
case "webapps-launch":
|
||||
this.openURL(data.manifestURL, data.origin);
|
||||
break;
|
||||
case "webapps-uninstall":
|
||||
sendMessageToJava({
|
||||
type: "Webapps:Uninstall",
|
||||
origin: data.origin
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
doInstall: function doInstall(aData) {
|
||||
let jsonManifest = aData.isPackage ? aData.app.updateManifest : aData.app.manifest;
|
||||
let manifest = new ManifestHelper(jsonManifest, aData.app.origin);
|
||||
|
||||
if (Services.prompt.confirm(null, Strings.browser.GetStringFromName("webapps.installTitle"), manifest.name + "\n" + aData.app.origin)) {
|
||||
// Get a profile for the app to be installed in. We'll download everything before creating the icons.
|
||||
let origin = aData.app.origin;
|
||||
sendMessageToJava({
|
||||
type: "Webapps:Preinstall",
|
||||
name: manifest.name,
|
||||
manifestURL: aData.app.manifestURL,
|
||||
origin: origin
|
||||
}, (data) => {
|
||||
let profilePath = data.profile;
|
||||
if (!profilePath)
|
||||
return;
|
||||
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
|
||||
file.initWithPath(profilePath);
|
||||
|
||||
let self = this;
|
||||
DOMApplicationRegistry.confirmInstall(aData, file,
|
||||
function (aManifest) {
|
||||
let localeManifest = new ManifestHelper(aManifest, aData.app.origin);
|
||||
|
||||
// the manifest argument is the manifest from within the zip file,
|
||||
// TODO so now would be a good time to ask about permissions.
|
||||
self.makeBase64Icon(localeManifest.biggestIconURL || this.DEFAULT_ICON,
|
||||
function(scaledIcon, fullsizeIcon) {
|
||||
// if java returned a profile path to us, try to use it to pre-populate the app cache
|
||||
// also save the icon so that it can be used in the splash screen
|
||||
try {
|
||||
let iconFile = file.clone();
|
||||
iconFile.append("logo.png");
|
||||
let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Ci.nsIWebBrowserPersist);
|
||||
persist.persistFlags = Ci.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
|
||||
persist.persistFlags |= Ci.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
|
||||
|
||||
let source = Services.io.newURI(fullsizeIcon, "UTF8", null);
|
||||
persist.saveURI(source, null, null, null, null, iconFile, null);
|
||||
|
||||
// aData.app.origin may now point to the app: url that hosts this app
|
||||
sendMessageToJava({
|
||||
type: "Webapps:Postinstall",
|
||||
name: localeManifest.name,
|
||||
manifestURL: aData.app.manifestURL,
|
||||
originalOrigin: origin,
|
||||
origin: aData.app.origin,
|
||||
iconURL: fullsizeIcon
|
||||
});
|
||||
if (!!aData.isPackage) {
|
||||
// For packaged apps, put a notification in the notification bar.
|
||||
let message = Strings.browser.GetStringFromName("webapps.alertSuccess");
|
||||
let alerts = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
|
||||
alerts.showAlertNotification("drawable://alert_app", localeManifest.name, message, true, "", {
|
||||
observe: function () {
|
||||
self.openURL(aData.app.manifestURL, aData.app.origin);
|
||||
}
|
||||
}, "webapp");
|
||||
}
|
||||
|
||||
// Create a system notification allowing the user to launch the app
|
||||
let observer = {
|
||||
observe: function (aSubject, aTopic) {
|
||||
if (aTopic == "alertclickcallback") {
|
||||
WebappsUI.openURL(aData.app.manifestURL, origin);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let message = Strings.browser.GetStringFromName("webapps.alertSuccess");
|
||||
let alerts = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
|
||||
alerts.showAlertNotification("drawable://alert_app", localeManifest.name, message, true, "", observer, "webapp");
|
||||
} catch(ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
self.writeDefaultPrefs(file, localeManifest);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
DOMApplicationRegistry.denyInstall(aData);
|
||||
}
|
||||
},
|
||||
|
||||
writeDefaultPrefs: function webapps_writeDefaultPrefs(aProfile, aManifest) {
|
||||
// build any app specific default prefs
|
||||
let prefs = [];
|
||||
if (aManifest.orientation) {
|
||||
prefs.push({name:"app.orientation.default", value: aManifest.orientation.join(",") });
|
||||
}
|
||||
|
||||
// write them into the app profile
|
||||
let defaultPrefsFile = aProfile.clone();
|
||||
defaultPrefsFile.append(this.DEFAULT_PREFS_FILENAME);
|
||||
this._writeData(defaultPrefsFile, prefs);
|
||||
},
|
||||
|
||||
_writeData: function(aFile, aPrefs) {
|
||||
if (aPrefs.length > 0) {
|
||||
let array = new TextEncoder().encode(JSON.stringify(aPrefs));
|
||||
OS.File.writeAtomic(aFile.path, array, { tmpPath: aFile.path + ".tmp" }).then(null, function onError(reason) {
|
||||
console.log("Error writing default prefs: " + reason);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
openURL: function openURL(aManifestURL, aOrigin) {
|
||||
sendMessageToJava({
|
||||
type: "Webapps:Open",
|
||||
manifestURL: aManifestURL,
|
||||
origin: aOrigin
|
||||
});
|
||||
},
|
||||
|
||||
get iconSize() {
|
||||
let iconSize = 64;
|
||||
try {
|
||||
let jni = new JNI();
|
||||
let cls = jni.findClass("org/mozilla/gecko/GeckoAppShell");
|
||||
let method = jni.getStaticMethodID(cls, "getPreferredIconSize", "()I");
|
||||
iconSize = jni.callStaticIntMethod(cls, method);
|
||||
jni.close();
|
||||
} catch(ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
|
||||
delete this.iconSize;
|
||||
return this.iconSize = iconSize;
|
||||
},
|
||||
|
||||
makeBase64Icon: function loadAndMakeBase64Icon(aIconURL, aCallbackFunction) {
|
||||
let size = this.iconSize;
|
||||
|
||||
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
canvas.width = canvas.height = size;
|
||||
let ctx = canvas.getContext("2d");
|
||||
let favicon = new Image();
|
||||
favicon.onload = function() {
|
||||
ctx.drawImage(favicon, 0, 0, size, size);
|
||||
let scaledIcon = canvas.toDataURL("image/png", "");
|
||||
|
||||
canvas.width = favicon.width;
|
||||
canvas.height = favicon.height;
|
||||
ctx.drawImage(favicon, 0, 0, favicon.width, favicon.height);
|
||||
let fullsizeIcon = canvas.toDataURL("image/png", "");
|
||||
|
||||
canvas = null;
|
||||
aCallbackFunction.call(null, scaledIcon, fullsizeIcon);
|
||||
};
|
||||
favicon.onerror = function() {
|
||||
Cu.reportError("CreateShortcut: favicon image load error");
|
||||
|
||||
// if the image failed to load, and it was not our default icon, attempt to
|
||||
// use our default as a fallback
|
||||
if (favicon.src != WebappsUI.DEFAULT_ICON) {
|
||||
favicon.src = WebappsUI.DEFAULT_ICON;
|
||||
}
|
||||
};
|
||||
|
||||
favicon.src = aIconURL;
|
||||
},
|
||||
|
||||
createShortcut: function createShortcut(aTitle, aURL, aIconURL, aType) {
|
||||
this.makeBase64Icon(aIconURL, function _createShortcut(icon) {
|
||||
try {
|
||||
let shell = Cc["@mozilla.org/browser/shell-service;1"].createInstance(Ci.nsIShellService);
|
||||
shell.createShortcut(aTitle, aURL, icon, aType);
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
var RemoteDebugger = {
|
||||
init: function rd_init() {
|
||||
Services.prefs.addObserver("devtools.debugger.", this, false);
|
||||
|
|
|
@ -113,12 +113,10 @@ contract @mozilla.org/snippets;1 {a78d7e59-b558-4321-a3d6-dffe2f1e76dd}
|
|||
category profile-after-change Snippets @mozilla.org/snippets;1
|
||||
category update-timer Snippets @mozilla.org/snippets;1,getService,snippets-update-timer,browser.snippets.updateInterval,86400
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
# WebappsUpdateTimer.js
|
||||
component {8f7002cb-e959-4f0a-a2e8-563232564385} WebappsUpdateTimer.js
|
||||
contract @mozilla.org/webapps-update-timer;1 {8f7002cb-e959-4f0a-a2e8-563232564385}
|
||||
category update-timer WebappsUpdateTimer @mozilla.org/webapps-update-timer;1,getService,webapp-background-update-timer,browser.webapps.updateInterval,86400
|
||||
#endif
|
||||
|
||||
# ColorPicker.js
|
||||
component {430b987f-bb9f-46a3-99a5-241749220b29} ColorPicker.js
|
||||
|
|
|
@ -67,8 +67,5 @@ MOZ_DATA_REPORTING=1
|
|||
# Enable runtime locale switching.
|
||||
MOZ_LOCALE_SWITCHER=1
|
||||
|
||||
# Enable the "synthetic APKs" implementation of Open Web Apps.
|
||||
MOZ_ANDROID_SYNTHAPKS=1
|
||||
|
||||
# Enable second screen and casting support for external devices.
|
||||
MOZ_DEVICES=1
|
||||
|
|
|
@ -621,10 +621,7 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
|
|||
@BINPATH@/components/marionettecomponent.js
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
@BINPATH@/components/WebappsUpdateTimer.js
|
||||
#endif
|
||||
|
||||
@BINPATH@/components/DataStore.manifest
|
||||
@BINPATH@/components/DataStoreImpl.js
|
||||
@BINPATH@/components/dom_datastore.xpt
|
||||
|
|
|
@ -242,16 +242,6 @@ timer.start=%S: timer started
|
|||
# %1$S=name of timer, %2$S=number of milliseconds
|
||||
timer.end=%1$S: %2$Sms
|
||||
|
||||
# Webapps
|
||||
webapps.installTitle=Install Application
|
||||
webapps.alertSuccess=Successfully installed
|
||||
# Shown when there is a generic problem installing an app
|
||||
webapps.installError=Error installing application
|
||||
# Shown when there is something wrong with an apps manifest
|
||||
webapps.manifestInstallError=Invalid application manifest
|
||||
# Shown when a network error prevented installing an app
|
||||
webapps.networkInstallError=Could not download manifest
|
||||
|
||||
# Click to play plugins
|
||||
clickToPlayPlugins.message2=%S contains plugin content. Would you like to activate it?
|
||||
clickToPlayPlugins.activate=Activate
|
||||
|
|
|
@ -37,9 +37,7 @@
|
|||
locale/@AB_CD@/browser/phishing.dtd (%chrome/phishing.dtd)
|
||||
locale/@AB_CD@/browser/payments.properties (%chrome/payments.properties)
|
||||
locale/@AB_CD@/browser/handling.properties (%chrome/handling.properties)
|
||||
#ifdef MOZ_ANDROID_SYNTHAPKS
|
||||
locale/@AB_CD@/browser/webapp.properties (%chrome/webapp.properties)
|
||||
#endif
|
||||
|
||||
# overrides for toolkit l10n, also for en-US
|
||||
relativesrcdir toolkit/locales:
|
||||
|
|
|
@ -22,16 +22,10 @@ EXTRA_JS_MODULES += [
|
|||
'SharedPreferences.jsm',
|
||||
'SimpleServiceDiscovery.jsm',
|
||||
'SSLExceptions.jsm',
|
||||
'WebappManagerWorker.js',
|
||||
]
|
||||
|
||||
EXTRA_PP_JS_MODULES += [
|
||||
'RokuApp.jsm',
|
||||
'WebappManager.jsm',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_ANDROID_SYNTHAPKS']:
|
||||
EXTRA_PP_JS_MODULES += [
|
||||
'WebappManager.jsm',
|
||||
]
|
||||
EXTRA_JS_MODULES += [
|
||||
'WebappManagerWorker.js',
|
||||
]
|
||||
|
|
Загрузка…
Ссылка в новой задаче