13918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott/* 23918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * Copyright (C) 2009 The Android Open Source Project 33918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * 43918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * Licensed under the Apache License, Version 2.0 (the "License"); 53918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * you may not use this file except in compliance with the License. 63918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * You may obtain a copy of the License at 73918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * 83918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * http://www.apache.org/licenses/LICENSE-2.0 93918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * 103918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * Unless required by applicable law or agreed to in writing, software 113918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * distributed under the License is distributed on an "AS IS" BASIS, 123918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * See the License for the specific language governing permissions and 143918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott * limitations under the License. 153918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott */ 163918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott 173918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottpackage com.android.browser; 183918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott 1930ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamathimport java.io.IOException; 2030ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamathimport java.net.HttpURLConnection; 2130ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamathimport java.net.URL; 228ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton 233918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.content.ContentResolver; 243918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.content.ContentValues; 25980e99536e2fc6f305432387fe92c9916fa6e7b6Henrik Baardimport android.content.Context; 263918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.database.Cursor; 273918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.graphics.Bitmap; 283918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.graphics.BitmapFactory; 293918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.os.AsyncTask; 30e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdochimport android.os.Bundle; 31e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdochimport android.os.Message; 32bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scrogginsimport android.provider.BrowserContract; 331a805652e389d9404ee0fda7c993a6202332e92bJeff Hamiltonimport android.provider.BrowserContract.Images; 343918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport android.webkit.WebView; 353918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott 363918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport java.io.ByteArrayOutputStream; 373918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scottimport java.io.InputStream; 383918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott 39a74f6963e548b7552d25fc4f851360dc74248958Patrick Scottclass DownloadTouchIcon extends AsyncTask<String, Void, Void> { 40bf6b54db8f42a42c218f17ec358563e66e8e95baJohn Reck 413918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott private final ContentResolver mContentResolver; 42c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins private Cursor mCursor; 433918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott private final String mOriginalUrl; 443918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott private final String mUrl; 45e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch private final String mUserAgent; // Sites may serve a different icon to different UAs 46e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch private Message mMessage; 47e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch 4822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba /* package */ Tab mTab; 493918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott 50e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch /** 51e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch * Use this ctor to store the touch icon in the bookmarks database for 52e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch * the originalUrl so we take account of redirects. Used when the user 53e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch * bookmarks a page from outside the bookmarks activity. 54e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch */ 5530ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath public DownloadTouchIcon(Tab tab, ContentResolver cr, WebView view) { 5622ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba mTab = tab; 573918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott mContentResolver = cr; 583918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott // Store these in case they change. 593918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott mOriginalUrl = view.getOriginalUrl(); 603918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott mUrl = view.getUrl(); 613918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott mUserAgent = view.getSettings().getUserAgentString(); 623918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott } 633918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott 64e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch /** 65e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch * Use this ctor to download the touch icon and update the bookmarks database 66e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch * entry for the given url. Used when the user creates a bookmark from 67e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch * within the bookmarks activity and there haven't been any redirects. 68e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch * TODO: Would be nice to set the user agent here so that there is no 69e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch * potential for the three different ctors here to return different icons. 70e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch */ 7130ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath public DownloadTouchIcon(ContentResolver cr, String url) { 7222ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba mTab = null; 733918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott mContentResolver = cr; 743918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott mOriginalUrl = null; 753918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott mUrl = url; 763918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott mUserAgent = null; 773918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott } 783918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott 79e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch /** 80e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch * Use this ctor to not store the touch icon in a database, rather add it to 81bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins * the passed Message's data bundle with the key 82bc92285a27fa629d630d3ea0d0608f13a6de5deeLeon Scroggins * {@link BrowserContract.Bookmarks#TOUCH_ICON} and then send the message. 83e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch */ 8430ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath public DownloadTouchIcon(Message msg, String userAgent) { 85e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch mMessage = msg; 86e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch mContentResolver = null; 87e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch mOriginalUrl = null; 88e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch mUrl = null; 89e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch mUserAgent = userAgent; 90e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch } 91e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch 923918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott @Override 93a74f6963e548b7552d25fc4f851360dc74248958Patrick Scott public Void doInBackground(String... values) { 94e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch if (mContentResolver != null) { 951a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton mCursor = Bookmarks.queryCombinedForUrl(mContentResolver, 968ce956c6076a89aae85856f35b94bad7fc8fa1f1Jeff Hamilton mOriginalUrl, mUrl); 97e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch } 98e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch 991a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton boolean inDatabase = mCursor != null && mCursor.getCount() > 0; 1003918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott 1011a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton if (inDatabase || mMessage != null) { 10230ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath HttpURLConnection connection = null; 103bf6b54db8f42a42c218f17ec358563e66e8e95baJohn Reck try { 10430ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath URL url = new URL(values[0]); 10530ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath connection = (HttpURLConnection) url.openConnection(); 10630ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath if (mUserAgent != null) { 10730ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath connection.addRequestProperty("User-Agent", mUserAgent); 108bf6b54db8f42a42c218f17ec358563e66e8e95baJohn Reck } 109d159ec534823b87f9896843e95912b0df8c27e16Andreas Sandblad 11030ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath if (connection.getResponseCode() == 200) { 11130ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath InputStream content = connection.getInputStream(); 11230ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath Bitmap icon = null; 11330ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath try { 11430ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath icon = BitmapFactory.decodeStream( 11530ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath content, null, null); 11630ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath } finally { 11730ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath try { 11830ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath content.close(); 11930ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath } catch (IOException ignored) { 120c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins } 1213918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott } 12230ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath 12330ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath if (inDatabase) { 12430ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath storeIcon(icon); 12530ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath } else if (mMessage != null) { 12630ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath Bundle b = mMessage.getData(); 12730ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath b.putParcelable(BrowserContract.Bookmarks.TOUCH_ICON, icon); 12830ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath } 1293918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott } 13030ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath } catch (IOException ignored) { 131c8393d9cfa47e3f5f279b17c412fd363e7ea94bdLeon Scroggins } finally { 13230ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath if (connection != null) { 13330ce2c541e4957b16cdbb3cce3a12494571d0254Narayan Kamath connection.disconnect(); 134bf6b54db8f42a42c218f17ec358563e66e8e95baJohn Reck } 1353918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott } 1363918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott } 137e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch 1388e9fe327af19df2df03a2546c97604b095acd5e1Patrick Scott if (mCursor != null) { 1398e9fe327af19df2df03a2546c97604b095acd5e1Patrick Scott mCursor.close(); 1408e9fe327af19df2df03a2546c97604b095acd5e1Patrick Scott } 141e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch 142e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch if (mMessage != null) { 143e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch mMessage.sendToTarget(); 144e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch } 145e322f56ac6f425e08018319fb00df2bbaf569e33Ben Murdoch 1463918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott return null; 1473918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott } 1483918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott 1493918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott @Override 15059ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott protected void onCancelled() { 15159ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott if (mCursor != null) { 15259ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott mCursor.close(); 15359ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott } 15459ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott } 15559ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott 156a74f6963e548b7552d25fc4f851360dc74248958Patrick Scott private void storeIcon(Bitmap icon) { 15759ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott // Do this first in case the download failed. 15822ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba if (mTab != null) { 15959ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott // Remove the touch icon loader from the BrowserActivity. 16022ac16eab0b62d24a99fc360f2ccea14837f4127Grace Kloba mTab.mTouchIconLoader = null; 16159ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott } 16259ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott 16359ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott if (icon == null || mCursor == null || isCancelled()) { 1643918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott return; 1653918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott } 16659ce830c6eab58171b727abe5282c4abadb1a040Patrick Scott 1673918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott if (mCursor.moveToFirst()) { 1681a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton final ByteArrayOutputStream os = new ByteArrayOutputStream(); 1691a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton icon.compress(Bitmap.CompressFormat.PNG, 100, os); 1701a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton 1711a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton ContentValues values = new ContentValues(); 1721a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton values.put(Images.TOUCH_ICON, os.toByteArray()); 1731a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton 1743918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott do { 1759e7686e110d3fd1e3ad7742ec27a1c7d54cf9408John Reck values.put(Images.URL, mCursor.getString(0)); 1761a805652e389d9404ee0fda7c993a6202332e92bJeff Hamilton mContentResolver.update(Images.CONTENT_URI, values, null, null); 1773918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott } while (mCursor.moveToNext()); 1783918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott } 1793918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott } 1803918d4443ff38ef1870e02aa51a8b29f8352bb1aPatrick Scott} 181