Home | History | Annotate | Download | only in browser
      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      */
     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      */
     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      */
     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
     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
    150     protected void onCancelled() {
    151         if (mCursor != null) {
    152             mCursor.close();
    153         }
    154     }
    155 
    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