1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.browser; 18 19 import java.io.IOException; 20 import java.net.HttpURLConnection; 21 import java.net.URL; 22 23 import android.content.ContentResolver; 24 import android.content.ContentValues; 25 import android.content.Context; 26 import android.database.Cursor; 27 import android.graphics.Bitmap; 28 import android.graphics.BitmapFactory; 29 import android.os.AsyncTask; 30 import android.os.Bundle; 31 import android.os.Message; 32 import android.provider.BrowserContract; 33 import android.provider.BrowserContract.Images; 34 import android.webkit.WebView; 35 36 import java.io.ByteArrayOutputStream; 37 import java.io.InputStream; 38 39 class DownloadTouchIcon extends AsyncTask<String, Void, Void> { 40 41 private final ContentResolver mContentResolver; 42 private Cursor mCursor; 43 private final String mOriginalUrl; 44 private final String mUrl; 45 private final String mUserAgent; // Sites may serve a different icon to different UAs 46 private Message mMessage; 47 48 /* package */ Tab mTab; 49 50 /** 51 * Use this ctor to store the touch icon in the bookmarks database for 52 * the originalUrl so we take account of redirects. Used when the user 53 * bookmarks a page from outside the bookmarks activity. 54 */ DownloadTouchIcon(Tab tab, ContentResolver cr, WebView view)55 public DownloadTouchIcon(Tab tab, ContentResolver cr, WebView view) { 56 mTab = tab; 57 mContentResolver = cr; 58 // Store these in case they change. 59 mOriginalUrl = view.getOriginalUrl(); 60 mUrl = view.getUrl(); 61 mUserAgent = view.getSettings().getUserAgentString(); 62 } 63 64 /** 65 * Use this ctor to download the touch icon and update the bookmarks database 66 * entry for the given url. Used when the user creates a bookmark from 67 * within the bookmarks activity and there haven't been any redirects. 68 * TODO: Would be nice to set the user agent here so that there is no 69 * potential for the three different ctors here to return different icons. 70 */ DownloadTouchIcon(ContentResolver cr, String url)71 public DownloadTouchIcon(ContentResolver cr, String url) { 72 mTab = null; 73 mContentResolver = cr; 74 mOriginalUrl = null; 75 mUrl = url; 76 mUserAgent = null; 77 } 78 79 /** 80 * Use this ctor to not store the touch icon in a database, rather add it to 81 * the passed Message's data bundle with the key 82 * {@link BrowserContract.Bookmarks#TOUCH_ICON} and then send the message. 83 */ DownloadTouchIcon(Message msg, String userAgent)84 public DownloadTouchIcon(Message msg, String userAgent) { 85 mMessage = msg; 86 mContentResolver = null; 87 mOriginalUrl = null; 88 mUrl = null; 89 mUserAgent = userAgent; 90 } 91 92 @Override doInBackground(String... values)93 public Void doInBackground(String... values) { 94 if (mContentResolver != null) { 95 mCursor = Bookmarks.queryCombinedForUrl(mContentResolver, 96 mOriginalUrl, mUrl); 97 } 98 99 boolean inDatabase = mCursor != null && mCursor.getCount() > 0; 100 101 if (inDatabase || mMessage != null) { 102 HttpURLConnection connection = null; 103 try { 104 URL url = new URL(values[0]); 105 connection = (HttpURLConnection) url.openConnection(); 106 if (mUserAgent != null) { 107 connection.addRequestProperty("User-Agent", mUserAgent); 108 } 109 110 if (connection.getResponseCode() == 200) { 111 InputStream content = connection.getInputStream(); 112 Bitmap icon = null; 113 try { 114 icon = BitmapFactory.decodeStream( 115 content, null, null); 116 } finally { 117 try { 118 content.close(); 119 } catch (IOException ignored) { 120 } 121 } 122 123 if (inDatabase) { 124 storeIcon(icon); 125 } else if (mMessage != null) { 126 Bundle b = mMessage.getData(); 127 b.putParcelable(BrowserContract.Bookmarks.TOUCH_ICON, icon); 128 } 129 } 130 } catch (IOException ignored) { 131 } finally { 132 if (connection != null) { 133 connection.disconnect(); 134 } 135 } 136 } 137 138 if (mCursor != null) { 139 mCursor.close(); 140 } 141 142 if (mMessage != null) { 143 mMessage.sendToTarget(); 144 } 145 146 return null; 147 } 148 149 @Override onCancelled()150 protected void onCancelled() { 151 if (mCursor != null) { 152 mCursor.close(); 153 } 154 } 155 storeIcon(Bitmap icon)156 private void storeIcon(Bitmap icon) { 157 // Do this first in case the download failed. 158 if (mTab != null) { 159 // Remove the touch icon loader from the BrowserActivity. 160 mTab.mTouchIconLoader = null; 161 } 162 163 if (icon == null || mCursor == null || isCancelled()) { 164 return; 165 } 166 167 if (mCursor.moveToFirst()) { 168 final ByteArrayOutputStream os = new ByteArrayOutputStream(); 169 icon.compress(Bitmap.CompressFormat.PNG, 100, os); 170 171 ContentValues values = new ContentValues(); 172 values.put(Images.TOUCH_ICON, os.toByteArray()); 173 174 do { 175 values.put(Images.URL, mCursor.getString(0)); 176 mContentResolver.update(Images.CONTENT_URI, values, null, null); 177 } while (mCursor.moveToNext()); 178 } 179 } 180 } 181