Bug 886996 - Set as wallpaper now sets wallpapers using a chooser. r=margaret

This commit is contained in:
Shilpan Bhagat 2013-08-02 13:33:30 -07:00
parent 8177c115bc
commit f8227ab819
10 changed files with 73 additions and 162 deletions

View File

@ -4207,7 +4207,6 @@ BUILD_CTYPES=1
MOZ_USE_NATIVE_POPUP_WINDOWS=
MOZ_ANDROID_HISTORY=
MOZ_WEBSMS_BACKEND=
MOZ_ANDROID_WALLPAPER=
MOZ_ANDROID_BEAM=
ACCESSIBILITY=1
MOZ_TIME_MANAGER=
@ -5166,13 +5165,6 @@ if test -n "$MOZ_WEBSMS_BACKEND"; then
AC_DEFINE(MOZ_WEBSMS_BACKEND)
fi
dnl ========================================================
dnl = Enable SET_WALLPAPER permission on Android
dnl ========================================================
if test -n "$MOZ_ANDROID_WALLPAPER"; then
AC_DEFINE(MOZ_ANDROID_WALLPAPER)
fi
dnl ========================================================
dnl = Enable NFC permission on Android
dnl ========================================================
@ -8612,7 +8604,6 @@ AC_SUBST(MOZ_METRO)
AC_SUBST(MOZ_ANDROID_HISTORY)
AC_SUBST(MOZ_WEBSMS_BACKEND)
AC_SUBST(MOZ_ANDROID_WALLPAPER)
AC_SUBST(MOZ_ANDROID_BEAM)
AC_SUBST(ENABLE_STRIP)
AC_SUBST(PKG_SKIP_STRIP)

View File

@ -99,6 +99,10 @@ public class ActivityHandlerHelper implements GeckoEventListener {
return mActivityResultHandlerMap.put(aHandler);
}
public void startIntentForActivity (Activity activity, Intent intent, ActivityResultHandler activityResultHandler) {
activity.startActivityForResult(intent, mActivityResultHandlerMap.put(activityResultHandler));
}
private int addIntentActivitiesToList(Context context, Intent intent, ArrayList<Prompt.PromptListItem> items, ArrayList<Intent> aIntents) {
PackageManager pm = context.getPackageManager();
List<ResolveInfo> lri = pm.queryIntentActivityOptions(GeckoAppShell.getGeckoInterface().getActivity().getComponentName(), null, intent, 0);

View File

@ -28,9 +28,6 @@
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.VIBRATE"/>
#ifdef MOZ_ANDROID_WALLPAPER
<uses-permission android:name="android.permission.SET_WALLPAPER"/>
#endif
<uses-permission android:name="@ANDROID_PACKAGE_NAME@.permissions.PASSWORD_PROVIDER"/>
<uses-permission android:name="@ANDROID_PACKAGE_NAME@.permissions.BROWSER_PROVIDER"/>
<uses-permission android:name="@ANDROID_PACKAGE_NAME@.permissions.FORMHISTORY_PROVIDER"/>

View File

@ -19,6 +19,7 @@ import org.mozilla.gecko.health.BrowserHealthRecorder;
import org.mozilla.gecko.health.BrowserHealthRecorder.SessionInformation;
import org.mozilla.gecko.updater.UpdateService;
import org.mozilla.gecko.updater.UpdateServiceHelper;
import org.mozilla.gecko.util.ActivityResultHandler;
import org.mozilla.gecko.util.EventDispatcher;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.GeckoEventResponder;
@ -63,6 +64,7 @@ import android.os.PowerManager;
import android.os.StrictMode;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.provider.MediaStore.Images.Media;
import android.telephony.CellLocation;
import android.telephony.NeighboringCellInfo;
@ -691,7 +693,7 @@ abstract public class GeckoApp
GeckoAppShell.shareImage(src, type);
} else if (event.equals("Wallpaper:Set")) {
String src = message.getString("url");
setImageAsWallpaper(src);
setImageAs(src);
} else if (event.equals("Sanitize:ClearHistory")) {
handleClearHistory();
} else if (event.equals("Update:Check")) {
@ -971,147 +973,71 @@ abstract public class GeckoApp
});
}
private void setImageAsWallpaper(final String aSrc) {
final String progText = getString(R.string.wallpaper_progress);
final String successText = getString(R.string.wallpaper_success);
final String failureText = getString(R.string.wallpaper_fail);
final String fileName = aSrc.substring(aSrc.lastIndexOf("/") + 1);
final PendingIntent emptyIntent = PendingIntent.getActivity(this, 0, new Intent(), 0);
final AlertNotification notification = new AlertNotification(this, fileName.hashCode(),
R.drawable.alert_download, fileName, progText, System.currentTimeMillis(), null);
notification.setLatestEventInfo(this, fileName, progText, emptyIntent );
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.show();
new UiAsyncTask<Void, Void, Boolean>(ThreadUtils.getBackgroundHandler()) {
// This method starts downloading an image synchronously and displays the Chooser activity to set the image as wallpaper.
private void setImageAs(final String aSrc) {
boolean isDataURI = aSrc.startsWith("data:");
Bitmap image = null;
InputStream is = null;
ByteArrayOutputStream os = null;
try {
if (isDataURI) {
int dataStart = aSrc.indexOf(",");
byte[] buf = Base64.decode(aSrc.substring(dataStart+1), Base64.DEFAULT);
image = BitmapUtils.decodeByteArray(buf);
} else {
int byteRead;
byte[] buf = new byte[4192];
os = new ByteArrayOutputStream();
URL url = new URL(aSrc);
is = url.openStream();
@Override
protected Boolean doInBackground(Void... params) {
WallpaperManager mgr = WallpaperManager.getInstance(GeckoApp.this);
if (mgr == null) {
return false;
// Cannot read from same stream twice. Also, InputStream from
// URL does not support reset. So converting to byte array.
while((byteRead = is.read(buf)) != -1) {
os.write(buf, 0, byteRead);
}
byte[] imgBuffer = os.toByteArray();
image = BitmapUtils.decodeByteArray(imgBuffer);
}
if (image != null) {
String path = Media.insertImage(getContentResolver(),image, null, null);
final Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse(path));
// Determine the ideal width and height of the wallpaper
// for the device
int idealWidth = mgr.getDesiredMinimumWidth();
int idealHeight = mgr.getDesiredMinimumHeight();
// Sometimes WallpaperManager's getDesiredMinimum*() methods
// can return 0 if a Remote Exception occurs when calling the
// Wallpaper Service. So if that fails, we are calculating
// the ideal width and height from the device's display
// resolution (excluding the decorated area)
if (idealWidth <= 0 || idealHeight <= 0) {
int orientation;
Display defaultDisplay = getWindowManager().getDefaultDisplay();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
orientation = defaultDisplay.getRotation();
} else {
orientation = defaultDisplay.getOrientation();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
Point size = new Point();
defaultDisplay.getSize(size);
// The ideal wallpaper width is always twice the size of
// display width
if (orientation == Surface.ROTATION_0 || orientation == Surface.ROTATION_270) {
idealWidth = size.x * 2;
idealHeight = size.y;
} else {
idealWidth = size.y;
idealHeight = size.x * 2;
}
} else {
if (orientation == Surface.ROTATION_0 || orientation == Surface.ROTATION_270) {
idealWidth = defaultDisplay.getWidth() * 2;
idealHeight = defaultDisplay.getHeight();
} else {
idealWidth = defaultDisplay.getHeight();
idealHeight = defaultDisplay.getWidth() * 2;
}
}
}
boolean isDataURI = aSrc.startsWith("data:");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap image = null;
InputStream is = null;
ByteArrayOutputStream os = null;
try{
if (isDataURI) {
int dataStart = aSrc.indexOf(',');
byte[] buf = Base64.decode(aSrc.substring(dataStart+1), Base64.DEFAULT);
BitmapUtils.decodeByteArray(buf, options);
options.inSampleSize = getBitmapSampleSize(options, idealWidth, idealHeight);
options.inJustDecodeBounds = false;
image = BitmapUtils.decodeByteArray(buf, options);
} else {
int byteRead;
byte[] buf = new byte[4192];
os = new ByteArrayOutputStream();
URL url = new URL(aSrc);
is = url.openStream();
// Cannot read from same stream twice. Also, InputStream from
// URL does not support reset. So converting to byte array
while((byteRead = is.read(buf)) != -1) {
os.write(buf, 0, byteRead);
}
byte[] imgBuffer = os.toByteArray();
BitmapUtils.decodeByteArray(imgBuffer, options);
options.inSampleSize = getBitmapSampleSize(options, idealWidth, idealHeight);
options.inJustDecodeBounds = false;
image = BitmapUtils.decodeByteArray(imgBuffer, options);
}
if(image != null) {
mgr.setBitmap(image);
return true;
} else {
return false;
}
} catch(OutOfMemoryError ome) {
Log.e(LOGTAG, "Out of Memory when converting to byte array", ome);
return false;
// Removes the image from storage once the chooser activity ends.
GeckoAppShell.sActivityHelper.startIntentForActivity(this,
Intent.createChooser(intent, sAppContext.getString(R.string.set_image_chooser_title)),
new ActivityResultHandler() {
@Override
public void onActivityResult (int resultCode, Intent data) {
getContentResolver().delete(intent.getData(), null, null);
}
});
} else {
Toast.makeText(sAppContext, R.string.set_image_fail, Toast.LENGTH_SHORT).show();
}
} catch(OutOfMemoryError ome) {
Log.e(LOGTAG, "Out of Memory when converting to byte array", ome);
} catch(IOException ioe) {
Log.e(LOGTAG, "I/O Exception while setting wallpaper", ioe);
} finally {
if (is != null) {
try {
is.close();
} catch(IOException ioe) {
Log.e(LOGTAG, "I/O Exception while setting wallpaper", ioe);
return false;
} finally {
if(is != null) {
try {
is.close();
} catch(IOException ioe) {
Log.w(LOGTAG, "I/O Exception while closing stream", ioe);
}
}
if(os != null) {
try {
os.close();
} catch(IOException ioe) {
Log.w(LOGTAG, "I/O Exception while closing stream", ioe);
}
}
Log.w(LOGTAG, "I/O Exception while closing stream", ioe);
}
}
@Override
protected void onPostExecute(Boolean success) {
notification.cancel();
notification.flags = 0;
notification.flags |= Notification.FLAG_AUTO_CANCEL;
if(!success) {
notification.tickerText = failureText;
notification.setLatestEventInfo(GeckoApp.this, fileName, failureText, emptyIntent);
} else {
notification.tickerText = successText;
notification.setLatestEventInfo(GeckoApp.this, fileName, successText, emptyIntent);
if (os != null) {
try {
os.close();
} catch(IOException ioe) {
Log.w(LOGTAG, "I/O Exception while closing stream", ioe);
}
notification.show();
}
}.execute();
}
}
private int getBitmapSampleSize(BitmapFactory.Options options, int idealWidth, int idealHeight) {

View File

@ -195,9 +195,8 @@ size. -->
<!ENTITY tabs_normal "Tabs">
<!ENTITY tabs_private "Private">
<!ENTITY tabs_synced "Synced">
<!ENTITY wallpaper_success "Wallpaper updated">
<!ENTITY wallpaper_progress "Setting wallpaper">
<!ENTITY wallpaper_fail "Unable to set wallpaper">
<!ENTITY set_image_fail "Unable to set image">
<!ENTITY set_image_chooser_title "Set Image As">
<!-- Localization note (find_text, find_prev, find_next, find_close) : These strings are used
as alternate text for accessibility. They are not visible in the UI. -->

View File

@ -321,10 +321,9 @@
<!-- Search suggestions opt-in -->
<string name="suggestions_prompt">&suggestions_prompt2;</string>
<!-- Wallpaper Notifications -->
<string name="wallpaper_success">&wallpaper_success;</string>
<string name="wallpaper_progress">&wallpaper_progress;</string>
<string name="wallpaper_fail">&wallpaper_fail;</string>
<!-- Set Image Notifications -->
<string name="set_image_fail">&set_image_fail;</string>
<string name="set_image_chooser_title">&set_image_chooser_title;</string>
<!-- Contacts API -->
<string name="contacts_account_chooser_dialog_title">Share contacts from...</string>

View File

@ -23,7 +23,7 @@ public class testWebContentContextMenu extends PixelTest {
String urls [] = { "/robocop/robocop_big_link.html", "/robocop/robocop_big_mailto.html", "/robocop/robocop_picture_link.html"};
String linkMenuItems [] = { "Open Link in New Tab", "Open Link in Private Tab", "Copy Link", "Share Link", "Bookmark Link"};
String mailtoMenuItems [] = { "Open With an App", "Copy Email Address", "Share Email Address"};
String photoMenuItems [] = { "Copy Image Location", "Share Image", "Set as Wallpaper", "Save Image"};
String photoMenuItems [] = { "Copy Image Location", "Share Image", "Set Image As", "Save Image"};
verfyLinkContextMenu(linkMenuItems, urls);
verfyMailtoContextMenu(mailtoMenuItems, urls);
@ -192,7 +192,7 @@ public class testWebContentContextMenu extends PixelTest {
mSolo.waitForText("Picture Link");
}
else {
if (opt.equals("Set as Wallpaper")) {
if (opt.equals("Set Image As")) {
openContextMenu(2, urls);
mAsserter.ok(mSolo.waitForText(opt), "Waiting for " + opt + " option", "The " + opt + " option is present");
}

View File

@ -595,8 +595,7 @@ var BrowserApp = {
aTarget.ownerDocument);
});
#ifdef MOZ_ANDROID_WALLPAPER
NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.setWallpaper"),
NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.setImageAs"),
NativeWindow.contextmenus.imageSaveableContext,
function(aTarget) {
let src = aTarget.src;
@ -605,7 +604,6 @@ var BrowserApp = {
url: src
});
});
#endif
NativeWindow.contextmenus.add(
function(aTarget) {

View File

@ -19,9 +19,6 @@ MOZ_DISABLE_CRYPTOLEGACY=1
# Enable getUserMedia
MOZ_MEDIA_NAVIGATOR=1
# Enable SET_WALLPAPER permission
MOZ_ANDROID_WALLPAPER=1
# Enable NFC permission
MOZ_ANDROID_BEAM=1

View File

@ -170,7 +170,7 @@ contextmenu.shareImage=Share Image
# the text you have selected. %S is the name of the search engine. For example, "Google".
contextmenu.search=%S Search
contextmenu.saveImage=Save Image
contextmenu.setWallpaper=Set as Wallpaper
contextmenu.setImageAs=Set Image As
contextmenu.addSearchEngine=Add Search Engine
contextmenu.playMedia=Play
contextmenu.pauseMedia=Pause