• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
DownloadTouchIcon(Tab tab, Context ctx, ContentResolver cr, WebView view)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      */
DownloadTouchIcon(Context ctx, ContentResolver cr, String url)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      */
DownloadTouchIcon(Context context, Message msg, String userAgent)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
doInBackground(String... values)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
onCancelled()168     protected void onCancelled() {
169         if (mCursor != null) {
170             mCursor.close();
171         }
172     }
173 
storeIcon(Bitmap icon)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