diff options
author | George Mount <mount@google.com> | 2011-10-07 15:57:53 -0700 |
---|---|---|
committer | George Mount <mount@google.com> | 2011-10-10 13:11:56 -0700 |
commit | 387d45d2284c7fd7f12cbadc96161f946ae29cad (patch) | |
tree | 04bc0d8cdcca96dc2d5730f26309885f55d99d95 /src/com/android/browser | |
parent | 07af26d9ae4239bad876e8fd7ac69984a1d66996 (diff) | |
download | packages_apps_Browser-387d45d2284c7fd7f12cbadc96161f946ae29cad.zip packages_apps_Browser-387d45d2284c7fd7f12cbadc96161f946ae29cad.tar.gz packages_apps_Browser-387d45d2284c7fd7f12cbadc96161f946ae29cad.tar.bz2 |
Data URL fixes - bookmarks, save, and wallpaper
Bug 5383517
Images kept in data URLs can now be selected and this fixes the
Save and Set Wallpaper options. It also removes the bookmarking
capability.
Change-Id: I461bdcb4c950f6fcd8db8b38f4c599212106b027
Diffstat (limited to 'src/com/android/browser')
-rw-r--r-- | src/com/android/browser/Controller.java | 70 | ||||
-rw-r--r-- | src/com/android/browser/DataUri.java | 74 | ||||
-rw-r--r-- | src/com/android/browser/NavigationBarTablet.java | 20 | ||||
-rw-r--r-- | src/com/android/browser/PhoneUi.java | 4 | ||||
-rw-r--r-- | src/com/android/browser/WallpaperHandler.java | 37 |
5 files changed, 189 insertions, 16 deletions
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java index 282d4f2..81ba941 100644 --- a/src/com/android/browser/Controller.java +++ b/src/com/android/browser/Controller.java @@ -40,6 +40,7 @@ import android.net.Uri; import android.net.http.SslError; import android.os.AsyncTask; import android.os.Bundle; +import android.os.Environment; import android.os.Handler; import android.os.Message; import android.os.PowerManager; @@ -68,6 +69,7 @@ import android.view.View; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; import android.webkit.HttpAuthHandler; +import android.webkit.MimeTypeMap; import android.webkit.SslErrorHandler; import android.webkit.ValueCallback; import android.webkit.WebChromeClient; @@ -86,9 +88,15 @@ import com.android.browser.search.SearchEngine; import com.android.common.Search; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.net.URLEncoder; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -140,7 +148,7 @@ public class Controller // "source" parameter for Google search through simplily type final static String GOOGLE_SEARCH_SOURCE_TYPE = "browser-type"; - // "no-crash-recovery" parameter in intetnt to suppress crash recovery + // "no-crash-recovery" parameter in intent to suppress crash recovery final static String NO_CRASH_RECOVERY = "no-crash-recovery"; // A bitmap that is re-used in createScreenshot as scratch space @@ -2048,10 +2056,16 @@ public class Controller private Activity mActivity; private String mText; private boolean mPrivateBrowsing; + private static final String FALLBACK_EXTENSION = "dat"; + private static final String IMAGE_BASE_FORMAT = "yyyy-MM-dd-HH-mm-ss-"; public boolean onMenuItemClick(MenuItem item) { - DownloadHandler.onDownloadStartNoStream(mActivity, mText, null, - null, null, mPrivateBrowsing); + if (DataUri.isDataUri(mText)) { + saveDataUri(); + } else { + DownloadHandler.onDownloadStartNoStream(mActivity, mText, null, + null, null, mPrivateBrowsing); + } return true; } @@ -2060,6 +2074,56 @@ public class Controller mText = toDownload; mPrivateBrowsing = privateBrowsing; } + + /** + * Treats mText as a data URI and writes its contents to a file + * based on the current time. + */ + private void saveDataUri() { + FileOutputStream outputStream = null; + try { + DataUri uri = new DataUri(mText); + File target = getTarget(uri); + outputStream = new FileOutputStream(target); + outputStream.write(uri.getData()); + final DownloadManager manager = + (DownloadManager) mActivity.getSystemService(Context.DOWNLOAD_SERVICE); + manager.addCompletedDownload(target.getName(), + mActivity.getTitle().toString(), false, + uri.getMimeType(), target.getAbsolutePath(), + (long)uri.getData().length, false); + } catch (IOException e) { + Log.e(LOGTAG, "Could not save data URL"); + } finally { + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + // ignore close errors + } + } + } + } + + /** + * Creates a File based on the current time stamp and uses + * the mime type of the DataUri to get the extension. + */ + private File getTarget(DataUri uri) throws IOException { + File dir = mActivity.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS); + DateFormat format = new SimpleDateFormat(IMAGE_BASE_FORMAT); + String nameBase = format.format(new Date()); + String mimeType = uri.getMimeType(); + MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); + String extension = mimeTypeMap.getExtensionFromMimeType(mimeType); + if (extension == null) { + Log.w(LOGTAG, "Unknown mime type in data URI" + mimeType); + extension = FALLBACK_EXTENSION; + } + extension = "." + extension; // createTempFile needs the '.' + File targetFile = File.createTempFile(nameBase, extension, dir); + return targetFile; + } } private static class SelectText implements OnMenuItemClickListener { diff --git a/src/com/android/browser/DataUri.java b/src/com/android/browser/DataUri.java new file mode 100644 index 0000000..642b060 --- /dev/null +++ b/src/com/android/browser/DataUri.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.browser; + +import java.net.MalformedURLException; + +import libcore.io.Base64; + +/** + * Class extracts the mime type and data from a data uri. + * A data URI is of the form: + * <pre> + * data:[<MIME-type>][;charset=<encoding>][;base64],<data> + * </pre> + */ +public class DataUri { + private static final String DATA_URI_PREFIX = "data:"; + private static final String BASE_64_ENCODING = ";base64"; + + private String mMimeType; + private byte[] mData; + + public DataUri(String uri) throws MalformedURLException { + if (!isDataUri(uri)) { + throw new MalformedURLException("Not a data URI"); + } + + int commaIndex = uri.indexOf(',', DATA_URI_PREFIX.length()); + if (commaIndex < 0) { + throw new MalformedURLException("Comma expected in data URI"); + } + String contentType = uri.substring(DATA_URI_PREFIX.length(), + commaIndex); + mData = uri.substring(commaIndex + 1).getBytes(); + if (contentType.contains(BASE_64_ENCODING)) { + mData = Base64.decode(mData); + } + int semiIndex = contentType.indexOf(';'); + if (semiIndex > 0) { + mMimeType = contentType.substring(0, semiIndex); + } else { + mMimeType = contentType; + } + } + + /** + * Returns true if the text passed in appears to be a data URI. + */ + public static boolean isDataUri(String text) + { + return text.startsWith(DATA_URI_PREFIX); + } + + public String getMimeType() { + return mMimeType; + } + + public byte[] getData() { + return mData; + } +} diff --git a/src/com/android/browser/NavigationBarTablet.java b/src/com/android/browser/NavigationBarTablet.java index c22b1a0..be3a9ab 100644 --- a/src/com/android/browser/NavigationBarTablet.java +++ b/src/com/android/browser/NavigationBarTablet.java @@ -151,6 +151,12 @@ public class NavigationBarTablet extends NavigationBarBase { } @Override + public void onTabDataChanged(Tab tab) { + super.onTabDataChanged(tab); + showHideStar(tab); + } + + @Override public void setCurrentUrlIsBookmark(boolean isBookmark) { mStar.setActivated(isBookmark); } @@ -235,7 +241,7 @@ public class NavigationBarTablet extends NavigationBarBase { } mGoButton.setVisibility(View.GONE); mVoiceSearch.setVisibility(View.GONE); - mStar.setVisibility(View.VISIBLE); + showHideStar(mUiController.getCurrentTab()); mClearButton.setVisibility(View.GONE); if (mTitleBar.useQuickControls()) { mSearchButton.setVisibility(View.GONE); @@ -321,4 +327,16 @@ public class NavigationBarTablet extends NavigationBarBase { combo.start(); } + private void showHideStar(Tab tab) { + // hide the bookmark star for data URLs + if (tab != null && tab.inForeground()) { + int starVisibility = View.VISIBLE; + String url = tab.getUrl(); + if (DataUri.isDataUri(url)) { + starVisibility = View.GONE; + } + mStar.setVisibility(starVisibility); + } + } + } diff --git a/src/com/android/browser/PhoneUi.java b/src/com/android/browser/PhoneUi.java index 0e2710d..ddb4e0e 100644 --- a/src/com/android/browser/PhoneUi.java +++ b/src/com/android/browser/PhoneUi.java @@ -196,7 +196,9 @@ public class PhoneUi extends BaseUi { public void updateMenuState(Tab tab, Menu menu) { MenuItem bm = menu.findItem(R.id.bookmarks_menu_id); if (bm != null) { - bm.setVisible(!showingNavScreen()); + String url = tab.getUrl(); + boolean isDataUrl = DataUri.isDataUri(url); + bm.setVisible(!showingNavScreen() && !isDataUrl); } MenuItem nt = menu.findItem(R.id.new_tab_menu_id); if (nt != null) { diff --git a/src/com/android/browser/WallpaperHandler.java b/src/com/android/browser/WallpaperHandler.java index 6437b1a..b76861c 100644 --- a/src/com/android/browser/WallpaperHandler.java +++ b/src/com/android/browser/WallpaperHandler.java @@ -27,8 +27,8 @@ import android.graphics.drawable.Drawable; import android.util.Log; import android.view.MenuItem; import android.view.MenuItem.OnMenuItemClickListener; - import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; @@ -41,24 +41,19 @@ import java.net.URL; public class WallpaperHandler extends Thread implements OnMenuItemClickListener, DialogInterface.OnCancelListener { - private static final String LOGTAG = "WallpaperHandler"; // This should be large enough for BitmapFactory to decode the header so // that we can mark and reset the input stream to avoid duplicate network i/o private static final int BUFFER_SIZE = 128 * 1024; private Context mContext; - private URL mUrl; + private String mUrl; private ProgressDialog mWallpaperProgress; private boolean mCanceled = false; public WallpaperHandler(Context context, String url) { mContext = context; - try { - mUrl = new URL(url); - } catch (MalformedURLException e) { - mUrl = null; - } + mUrl = url; } @Override @@ -97,7 +92,7 @@ public class WallpaperHandler extends Thread // version and instead open an input stream on that. This pattern // could also be used in the download manager where the same problem // exists. - inputstream = mUrl.openStream(); + inputstream = openStream(); if (inputstream != null) { if (!inputstream.markSupported()) { inputstream = new BufferedInputStream(inputstream, BUFFER_SIZE); @@ -118,7 +113,7 @@ public class WallpaperHandler extends Thread int bmHeight = options.outHeight; int scale = 1; - while (bmWidth > maxWidth || bmHeight > maxWidth) { + while (bmWidth > maxWidth || bmHeight > maxHeight) { scale <<= 1; bmWidth >>= 1; bmHeight >>= 1; @@ -131,7 +126,7 @@ public class WallpaperHandler extends Thread // BitmapFactory read more than we could buffer // Re-open the stream inputstream.close(); - inputstream = mUrl.openStream(); + inputstream = openStream(); } Bitmap scaledWallpaper = BitmapFactory.decodeStream(inputstream, null, options); @@ -175,4 +170,24 @@ public class WallpaperHandler extends Thread mWallpaperProgress.dismiss(); } } + + /** + * Opens the input stream for the URL that the class should + * use to set the wallpaper. Abstracts the difference between + * standard URLs and data URLs. + * @return An open InputStream for the data at the URL + * @throws IOException if there is an error opening the URL stream + * @throws MalformedURLException if the URL is malformed + */ + private InputStream openStream() throws IOException, MalformedURLException { + InputStream inputStream = null; + if (DataUri.isDataUri(mUrl)) { + DataUri dataUri = new DataUri(mUrl); + inputStream = new ByteArrayInputStream(dataUri.getData()); + } else { + URL url = new URL(mUrl); + inputStream = url.openStream(); + } + return inputStream; + } } |