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 org.apache.http.HttpEntity;
     20 import org.apache.http.HttpHost;
     21 import org.apache.http.HttpResponse;
     22 import org.apache.http.client.methods.HttpGet;
     23 import org.apache.http.client.params.HttpClientParams;
     24 import org.apache.http.conn.params.ConnRouteParams;
     25 
     26 import android.content.ContentResolver;
     27 import android.content.ContentValues;
     28 import android.content.Context;
     29 import android.database.Cursor;
     30 import android.graphics.Bitmap;
     31 import android.graphics.BitmapFactory;
     32 import android.net.Proxy;
     33 import android.net.http.AndroidHttpClient;
     34 import android.os.AsyncTask;
     35 import android.os.Bundle;
     36 import android.os.Message;
     37 import android.provider.BrowserContract;
     38 import android.provider.BrowserContract.Images;
     39 import android.webkit.WebView;
     40 
     41 import java.io.ByteArrayOutputStream;
     42 import java.io.InputStream;
     43 
     44 class DownloadTouchIcon extends AsyncTask<String, Void, Void> {
     45 
     46     private final ContentResolver mContentResolver;
     47     private Cursor mCursor;
     48     private final String mOriginalUrl;
     49     private final String mUrl;
     50     private final String mUserAgent; // Sites may serve a different icon to different UAs
     51     private Message mMessage;
     52 
     53     private final Context mContext;
     54     /* package */ Tab mTab;
     55 
     56     /**
     57      * Use this ctor to store the touch icon in the bookmarks database for
     58      * the originalUrl so we take account of redirects. Used when the user
     59      * bookmarks a page from outside the bookmarks activity.
     60      */
     61     public DownloadTouchIcon(Tab tab, Context ctx, ContentResolver cr, WebView view) {
     62         mTab = tab;
     63         mContext = ctx.getApplicationContext();
     64         mContentResolver = cr;
     65         // Store these in case they change.
     66         mOriginalUrl = view.getOriginalUrl();
     67         mUrl = view.getUrl();
     68         mUserAgent = view.getSettings().getUserAgentString();
     69     }
     70 
     71     /**
     72      * Use this ctor to download the touch icon and update the bookmarks database
     73      * entry for the given url. Used when the user creates a bookmark from
     74      * within the bookmarks activity and there haven't been any redirects.
     75      * TODO: Would be nice to set the user agent here so that there is no
     76      * potential for the three different ctors here to return different icons.
     77      */
     78     public DownloadTouchIcon(Context ctx, ContentResolver cr, String url) {
     79         mTab = null;
     80         mContext = ctx.getApplicationContext();
     81         mContentResolver = cr;
     82         mOriginalUrl = null;
     83         mUrl = url;
     84         mUserAgent = null;
     85     }
     86 
     87     /**
     88      * Use this ctor to not store the touch icon in a database, rather add it to
     89      * the passed Message's data bundle with the key
     90      * {@link BrowserContract.Bookmarks#TOUCH_ICON} and then send the message.
     91      */
     92     public DownloadTouchIcon(Context context, Message msg, String userAgent) {
     93         mMessage = msg;
     94         mContext = context.getApplicationContext();
     95         mContentResolver = null;
     96         mOriginalUrl = null;
     97         mUrl = null;
     98         mUserAgent = userAgent;
     99     }
    100 
    101     @Override
    102     public Void doInBackground(String... values) {
    103         if (mContentResolver != null) {
    104             mCursor = Bookmarks.queryCombinedForUrl(mContentResolver,
    105                     mOriginalUrl, mUrl);
    106         }
    107 
    108         boolean inDatabase = mCursor != null && mCursor.getCount() > 0;
    109 
    110         String url = values[0];
    111 
    112         if (inDatabase || mMessage != null) {
    113             AndroidHttpClient client = null;
    114             HttpGet request = null;
    115 
    116             try {
    117                 client = AndroidHttpClient.newInstance(mUserAgent);
    118                 HttpHost httpHost = Proxy.getPreferredHttpHost(mContext, url);
    119                 if (httpHost != null) {
    120                     ConnRouteParams.setDefaultProxy(client.getParams(), httpHost);
    121                 }
    122 
    123                 request = new HttpGet(url);
    124 
    125                 // Follow redirects
    126                 HttpClientParams.setRedirecting(client.getParams(), true);
    127 
    128                 HttpResponse response = client.execute(request);
    129                 if (response.getStatusLine().getStatusCode() == 200) {
    130                     HttpEntity entity = response.getEntity();
    131                     if (entity != null) {
    132                         InputStream content = entity.getContent();
    133                         if (content != null) {
    134                             Bitmap icon = BitmapFactory.decodeStream(
    135                                     content, null, null);
    136                             if (inDatabase) {
    137                                 storeIcon(icon);
    138                             } else if (mMessage != null) {
    139                                 Bundle b = mMessage.getData();
    140                                 b.putParcelable(BrowserContract.Bookmarks.TOUCH_ICON, icon);
    141                             }
    142                         }
    143                     }
    144                 }
    145             } catch (Exception ex) {
    146                 if (request != null) {
    147                     request.abort();
    148                 }
    149             } finally {
    150                 if (client != null) {
    151                     client.close();
    152                 }
    153             }
    154         }
    155 
    156         if (mCursor != null) {
    157             mCursor.close();
    158         }
    159 
    160         if (mMessage != null) {
    161             mMessage.sendToTarget();
    162         }
    163 
    164         return null;
    165     }
    166 
    167     @Override
    168     protected void onCancelled() {
    169         if (mCursor != null) {
    170             mCursor.close();
    171         }
    172     }
    173 
    174     private void storeIcon(Bitmap icon) {
    175         // Do this first in case the download failed.
    176         if (mTab != null) {
    177             // Remove the touch icon loader from the BrowserActivity.
    178             mTab.mTouchIconLoader = null;
    179         }
    180 
    181         if (icon == null || mCursor == null || isCancelled()) {
    182             return;
    183         }
    184 
    185         if (mCursor.moveToFirst()) {
    186             final ByteArrayOutputStream os = new ByteArrayOutputStream();
    187             icon.compress(Bitmap.CompressFormat.PNG, 100, os);
    188 
    189             ContentValues values = new ContentValues();
    190             values.put(Images.TOUCH_ICON, os.toByteArray());
    191 
    192             do {
    193                 values.put(Images.URL, mCursor.getString(0));
    194                 mContentResolver.update(Images.CONTENT_URI, values, null, null);
    195             } while (mCursor.moveToNext());
    196         }
    197     }
    198 }
    199