blob: 11d64432ad5a0e2d9f1eda761f20639a13b9b0fa [file] [log] [blame]
The Android Open Source Project0c908882009-03-03 19:32:16 -08001/*
2 * Copyright (C) 2006 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
17package com.android.browser;
18
Ramanan Rajeswarandd4f4292009-03-24 20:41:19 -070019import com.google.android.providers.GoogleSettings.Partner;
The Android Open Source Projecta3c0aab2009-03-18 17:39:48 -070020
The Android Open Source Project0c908882009-03-03 19:32:16 -080021import android.app.SearchManager;
22import android.content.ComponentName;
23import android.content.ContentProvider;
24import android.content.ContentUris;
25import android.content.ContentValues;
26import android.content.Context;
27import android.content.Intent;
The Android Open Source Projecta3c0aab2009-03-18 17:39:48 -070028import android.content.SharedPreferences;
The Android Open Source Project0c908882009-03-03 19:32:16 -080029import android.content.UriMatcher;
The Android Open Source Projecta3c0aab2009-03-18 17:39:48 -070030import android.content.SharedPreferences.Editor;
The Android Open Source Project0c908882009-03-03 19:32:16 -080031import android.database.AbstractCursor;
32import android.database.Cursor;
The Android Open Source Project0c908882009-03-03 19:32:16 -080033import android.database.sqlite.SQLiteDatabase;
Bjorn Bringertbcd20b32009-04-29 21:52:09 +010034import android.database.sqlite.SQLiteOpenHelper;
The Android Open Source Project0c908882009-03-03 19:32:16 -080035import android.net.Uri;
The Android Open Source Projecta3c0aab2009-03-18 17:39:48 -070036import android.preference.PreferenceManager;
The Android Open Source Project0c908882009-03-03 19:32:16 -080037import android.provider.Browser;
The Android Open Source Project0c908882009-03-03 19:32:16 -080038import android.server.search.SearchableInfo;
Mike LeBeau21beb132009-05-13 14:57:50 -070039import android.text.TextUtils;
The Android Open Source Project0c908882009-03-03 19:32:16 -080040import android.text.util.Regex;
Bjorn Bringertbcd20b32009-04-29 21:52:09 +010041import android.util.Log;
42
43import java.util.Date;
The Android Open Source Project0c908882009-03-03 19:32:16 -080044
Ramanan Rajeswarandd4f4292009-03-24 20:41:19 -070045
The Android Open Source Project0c908882009-03-03 19:32:16 -080046public class BrowserProvider extends ContentProvider {
47
48 private SQLiteOpenHelper mOpenHelper;
49 private static final String sDatabaseName = "browser.db";
50 private static final String TAG = "BrowserProvider";
51 private static final String ORDER_BY = "visits DESC, date DESC";
52
The Android Open Source Projecta3c0aab2009-03-18 17:39:48 -070053 private static final String PICASA_URL = "http://picasaweb.google.com/m/" +
54 "viewer?source=androidclient";
55
The Android Open Source Project0c908882009-03-03 19:32:16 -080056 private static final String[] TABLE_NAMES = new String[] {
57 "bookmarks", "searches"
58 };
59 private static final String[] SUGGEST_PROJECTION = new String[] {
60 "_id", "url", "title", "bookmark"
61 };
62 private static final String SUGGEST_SELECTION =
63 "url LIKE ? OR url LIKE ? OR url LIKE ? OR url LIKE ?";
64 private String[] SUGGEST_ARGS = new String[4];
65
66 // shared suggestion array index, make sure to match COLUMNS
67 private static final int SUGGEST_COLUMN_INTENT_ACTION_ID = 1;
68 private static final int SUGGEST_COLUMN_INTENT_DATA_ID = 2;
69 private static final int SUGGEST_COLUMN_TEXT_1_ID = 3;
70 private static final int SUGGEST_COLUMN_TEXT_2_ID = 4;
71 private static final int SUGGEST_COLUMN_ICON_1_ID = 5;
72 private static final int SUGGEST_COLUMN_ICON_2_ID = 6;
73 private static final int SUGGEST_COLUMN_QUERY_ID = 7;
Mike LeBeau1ef26a32009-05-13 20:11:00 -070074 private static final int SUGGEST_COLUMN_FORMAT = 8;
The Android Open Source Project0c908882009-03-03 19:32:16 -080075
76 // shared suggestion columns
77 private static final String[] COLUMNS = new String[] {
78 "_id",
79 SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
80 SearchManager.SUGGEST_COLUMN_INTENT_DATA,
81 SearchManager.SUGGEST_COLUMN_TEXT_1,
82 SearchManager.SUGGEST_COLUMN_TEXT_2,
83 SearchManager.SUGGEST_COLUMN_ICON_1,
84 SearchManager.SUGGEST_COLUMN_ICON_2,
Mike LeBeau1ef26a32009-05-13 20:11:00 -070085 SearchManager.SUGGEST_COLUMN_QUERY,
86 SearchManager.SUGGEST_COLUMN_FORMAT};
The Android Open Source Project0c908882009-03-03 19:32:16 -080087
88 private static final int MAX_SUGGESTION_SHORT_ENTRIES = 3;
89 private static final int MAX_SUGGESTION_LONG_ENTRIES = 6;
90
91 // make sure that these match the index of TABLE_NAMES
92 private static final int URI_MATCH_BOOKMARKS = 0;
93 private static final int URI_MATCH_SEARCHES = 1;
94 // (id % 10) should match the table name index
95 private static final int URI_MATCH_BOOKMARKS_ID = 10;
96 private static final int URI_MATCH_SEARCHES_ID = 11;
97 //
98 private static final int URI_MATCH_SUGGEST = 20;
Bjorn Bringert346dafb2009-04-29 21:41:47 +010099 private static final int URI_MATCH_BOOKMARKS_SUGGEST = 21;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800100
101 private static final UriMatcher URI_MATCHER;
102
103 static {
104 URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
105 URI_MATCHER.addURI("browser", TABLE_NAMES[URI_MATCH_BOOKMARKS],
106 URI_MATCH_BOOKMARKS);
107 URI_MATCHER.addURI("browser", TABLE_NAMES[URI_MATCH_BOOKMARKS] + "/#",
108 URI_MATCH_BOOKMARKS_ID);
109 URI_MATCHER.addURI("browser", TABLE_NAMES[URI_MATCH_SEARCHES],
110 URI_MATCH_SEARCHES);
111 URI_MATCHER.addURI("browser", TABLE_NAMES[URI_MATCH_SEARCHES] + "/#",
112 URI_MATCH_SEARCHES_ID);
113 URI_MATCHER.addURI("browser", SearchManager.SUGGEST_URI_PATH_QUERY,
114 URI_MATCH_SUGGEST);
Bjorn Bringert346dafb2009-04-29 21:41:47 +0100115 URI_MATCHER.addURI("browser",
116 TABLE_NAMES[URI_MATCH_BOOKMARKS] + "/" + SearchManager.SUGGEST_URI_PATH_QUERY,
117 URI_MATCH_BOOKMARKS_SUGGEST);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800118 }
119
120 // 1 -> 2 add cache table
121 // 2 -> 3 update history table
122 // 3 -> 4 add passwords table
123 // 4 -> 5 add settings table
124 // 5 -> 6 ?
125 // 6 -> 7 ?
126 // 7 -> 8 drop proxy table
127 // 8 -> 9 drop settings table
128 // 9 -> 10 add form_urls and form_data
129 // 10 -> 11 add searches table
130 // 11 -> 12 modify cache table
131 // 12 -> 13 modify cache table
132 // 13 -> 14 correspond with Google Bookmarks schema
133 // 14 -> 15 move couple of tables to either browser private database or webview database
134 // 15 -> 17 Set it up for the SearchManager
135 // 17 -> 18 Added favicon in bookmarks table for Home shortcuts
136 // 18 -> 19 Remove labels table
137 private static final int DATABASE_VERSION = 19;
138
139 public BrowserProvider() {
140 }
141
142
Ramanan Rajeswarandd4f4292009-03-24 20:41:19 -0700143 private static CharSequence replaceSystemPropertyInString(Context context, CharSequence srcString) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800144 StringBuffer sb = new StringBuffer();
145 int lastCharLoc = 0;
Ramanan Rajeswarandd4f4292009-03-24 20:41:19 -0700146
147 final String client_id = Partner.getString(context.getContentResolver(), Partner.CLIENT_ID);
148
The Android Open Source Project0c908882009-03-03 19:32:16 -0800149 for (int i = 0; i < srcString.length(); ++i) {
150 char c = srcString.charAt(i);
151 if (c == '{') {
152 sb.append(srcString.subSequence(lastCharLoc, i));
153 lastCharLoc = i;
154 inner:
155 for (int j = i; j < srcString.length(); ++j) {
156 char k = srcString.charAt(j);
157 if (k == '}') {
158 String propertyKeyValue = srcString.subSequence(i + 1, j).toString();
Ramanan Rajeswarandd4f4292009-03-24 20:41:19 -0700159 if (propertyKeyValue.equals("CLIENT_ID")) {
160 sb.append(client_id);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800161 } else {
Ramanan Rajeswarandd4f4292009-03-24 20:41:19 -0700162 sb.append("unknown");
The Android Open Source Project0c908882009-03-03 19:32:16 -0800163 }
164 lastCharLoc = j + 1;
165 i = j;
166 break inner;
167 }
168 }
169 }
170 }
171 if (srcString.length() - lastCharLoc > 0) {
172 // Put on the tail, if there is one
173 sb.append(srcString.subSequence(lastCharLoc, srcString.length()));
174 }
175 return sb;
176 }
177
178 private static class DatabaseHelper extends SQLiteOpenHelper {
179 private Context mContext;
180
181 public DatabaseHelper(Context context) {
182 super(context, sDatabaseName, null, DATABASE_VERSION);
183 mContext = context;
184 }
185
186 @Override
187 public void onCreate(SQLiteDatabase db) {
188 db.execSQL("CREATE TABLE bookmarks (" +
189 "_id INTEGER PRIMARY KEY," +
190 "title TEXT," +
191 "url TEXT," +
192 "visits INTEGER," +
193 "date LONG," +
194 "created LONG," +
195 "description TEXT," +
196 "bookmark INTEGER," +
197 "favicon BLOB DEFAULT NULL" +
198 ");");
199
200 final CharSequence[] bookmarks = mContext.getResources()
201 .getTextArray(R.array.bookmarks);
202 int size = bookmarks.length;
203 try {
204 for (int i = 0; i < size; i = i + 2) {
Ramanan Rajeswarandd4f4292009-03-24 20:41:19 -0700205 CharSequence bookmarkDestination = replaceSystemPropertyInString(mContext, bookmarks[i + 1]);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800206 db.execSQL("INSERT INTO bookmarks (title, url, visits, " +
207 "date, created, bookmark)" + " VALUES('" +
208 bookmarks[i] + "', '" + bookmarkDestination +
209 "', 0, 0, 0, 1);");
210 }
211 } catch (ArrayIndexOutOfBoundsException e) {
212 }
213
214 db.execSQL("CREATE TABLE searches (" +
215 "_id INTEGER PRIMARY KEY," +
216 "search TEXT," +
217 "date LONG" +
218 ");");
219 }
220
221 @Override
222 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
223 Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
224 + newVersion + ", which will destroy all old data");
225 if (oldVersion == 18) {
226 db.execSQL("DROP TABLE IF EXISTS labels");
227 } else {
228 db.execSQL("DROP TABLE IF EXISTS bookmarks");
229 db.execSQL("DROP TABLE IF EXISTS searches");
230 onCreate(db);
231 }
232 }
233 }
234
235 @Override
236 public boolean onCreate() {
The Android Open Source Projecta3c0aab2009-03-18 17:39:48 -0700237 final Context context = getContext();
238 mOpenHelper = new DatabaseHelper(context);
239 // we added "picasa web album" into default bookmarks for version 19.
240 // To avoid erasing the bookmark table, we added it explicitly for
241 // version 18 and 19 as in the other cases, we will erase the table.
242 if (DATABASE_VERSION == 18 || DATABASE_VERSION == 19) {
243 SharedPreferences p = PreferenceManager
244 .getDefaultSharedPreferences(context);
245 boolean fix = p.getBoolean("fix_picasa", true);
246 if (fix) {
247 fixPicasaBookmark();
248 Editor ed = p.edit();
249 ed.putBoolean("fix_picasa", false);
250 ed.commit();
251 }
252 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800253 return true;
254 }
255
The Android Open Source Projecta3c0aab2009-03-18 17:39:48 -0700256 private void fixPicasaBookmark() {
257 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
258 Cursor cursor = db.rawQuery("SELECT _id FROM bookmarks WHERE " +
259 "bookmark = 1 AND url = ?", new String[] { PICASA_URL });
260 try {
261 if (!cursor.moveToFirst()) {
262 // set "created" so that it will be on the top of the list
263 db.execSQL("INSERT INTO bookmarks (title, url, visits, " +
264 "date, created, bookmark)" + " VALUES('" +
265 getContext().getString(R.string.picasa) + "', '"
266 + PICASA_URL + "', 0, 0, " + new Date().getTime()
267 + ", 1);");
268 }
269 } finally {
270 if (cursor != null) {
271 cursor.close();
272 }
273 }
274 }
275
The Android Open Source Project0c908882009-03-03 19:32:16 -0800276 /*
277 * Subclass AbstractCursor so we can combine multiple Cursors and add
278 * "Google Search".
279 * Here are the rules.
280 * 1. We only have MAX_SUGGESTION_LONG_ENTRIES in the list plus
281 * "Google Search";
282 * 2. If bookmark/history entries are less than
283 * (MAX_SUGGESTION_SHORT_ENTRIES -1), we include Google suggest.
284 */
285 private class MySuggestionCursor extends AbstractCursor {
286 private Cursor mHistoryCursor;
287 private Cursor mSuggestCursor;
288 private int mHistoryCount;
289 private int mSuggestionCount;
290 private boolean mBeyondCursor;
291 private String mString;
292
293 public MySuggestionCursor(Cursor hc, Cursor sc, String string) {
294 mHistoryCursor = hc;
295 mSuggestCursor = sc;
296 mHistoryCount = hc.getCount();
297 mSuggestionCount = sc != null ? sc.getCount() : 0;
298 if (mSuggestionCount > (MAX_SUGGESTION_LONG_ENTRIES - mHistoryCount)) {
299 mSuggestionCount = MAX_SUGGESTION_LONG_ENTRIES - mHistoryCount;
300 }
301 mString = string;
302 mBeyondCursor = false;
303 }
304
305 @Override
306 public boolean onMove(int oldPosition, int newPosition) {
307 if (mHistoryCursor == null) {
308 return false;
309 }
310 if (mHistoryCount > newPosition) {
311 mHistoryCursor.moveToPosition(newPosition);
312 mBeyondCursor = false;
313 } else if (mHistoryCount + mSuggestionCount > newPosition) {
314 mSuggestCursor.moveToPosition(newPosition - mHistoryCount);
315 mBeyondCursor = false;
316 } else {
317 mBeyondCursor = true;
318 }
319 return true;
320 }
321
322 @Override
323 public int getCount() {
324 if (mString.length() > 0) {
325 return mHistoryCount + mSuggestionCount + 1;
326 } else {
327 return mHistoryCount + mSuggestionCount;
328 }
329 }
330
331 @Override
332 public String[] getColumnNames() {
333 return COLUMNS;
334 }
Mike LeBeau21beb132009-05-13 14:57:50 -0700335
The Android Open Source Project0c908882009-03-03 19:32:16 -0800336 @Override
337 public String getString(int columnIndex) {
338 if ((mPos != -1 && mHistoryCursor != null)) {
339 switch(columnIndex) {
340 case SUGGEST_COLUMN_INTENT_ACTION_ID:
341 if (mHistoryCount > mPos) {
342 return Intent.ACTION_VIEW;
343 } else {
344 return Intent.ACTION_SEARCH;
345 }
346
347 case SUGGEST_COLUMN_INTENT_DATA_ID:
348 if (mHistoryCount > mPos) {
349 return mHistoryCursor.getString(1);
350 } else {
351 return null;
352 }
353
354 case SUGGEST_COLUMN_TEXT_1_ID:
355 if (mHistoryCount > mPos) {
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700356 return getHistoryTitle();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800357 } else if (!mBeyondCursor) {
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700358 return mSuggestCursor.getString(1);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800359 } else {
360 return mString;
361 }
362
363 case SUGGEST_COLUMN_TEXT_2_ID:
364 if (mHistoryCount > mPos) {
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700365 return getHistorySubtitle();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800366 } else if (!mBeyondCursor) {
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700367 return mSuggestCursor.getString(2);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800368 } else {
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700369 return getContext().getString(R.string.search_the_web);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800370 }
371
372 case SUGGEST_COLUMN_ICON_1_ID:
373 if (mHistoryCount > mPos) {
374 if (mHistoryCursor.getInt(3) == 1) {
375 return new Integer(
376 R.drawable.ic_search_category_bookmark)
377 .toString();
378 } else {
379 return new Integer(
380 R.drawable.ic_search_category_history)
381 .toString();
382 }
383 } else {
384 return new Integer(
385 R.drawable.ic_search_category_suggest)
386 .toString();
387 }
388
389 case SUGGEST_COLUMN_ICON_2_ID:
390 return new String("0");
391
392 case SUGGEST_COLUMN_QUERY_ID:
393 if (mHistoryCount > mPos) {
394 return null;
395 } else if (!mBeyondCursor) {
396 return mSuggestCursor.getString(3);
397 } else {
398 return mString;
399 }
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700400
401 case SUGGEST_COLUMN_FORMAT:
402 return "html";
The Android Open Source Project0c908882009-03-03 19:32:16 -0800403 }
404 }
405 return null;
406 }
407
408 @Override
409 public double getDouble(int column) {
410 throw new UnsupportedOperationException();
411 }
412
413 @Override
414 public float getFloat(int column) {
415 throw new UnsupportedOperationException();
416 }
417
418 @Override
419 public int getInt(int column) {
420 throw new UnsupportedOperationException();
421 }
422
423 @Override
424 public long getLong(int column) {
425 if ((mPos != -1) && column == 0) {
426 return mPos; // use row# as the _Id
427 }
428 throw new UnsupportedOperationException();
429 }
430
431 @Override
432 public short getShort(int column) {
433 throw new UnsupportedOperationException();
434 }
435
436 @Override
437 public boolean isNull(int column) {
438 throw new UnsupportedOperationException();
439 }
440
441 // TODO Temporary change, finalize after jq's changes go in
442 public void deactivate() {
443 if (mHistoryCursor != null) {
444 mHistoryCursor.deactivate();
445 }
446 if (mSuggestCursor != null) {
447 mSuggestCursor.deactivate();
448 }
449 super.deactivate();
450 }
451
452 public boolean requery() {
453 return (mHistoryCursor != null ? mHistoryCursor.requery() : false) |
454 (mSuggestCursor != null ? mSuggestCursor.requery() : false);
455 }
456
457 // TODO Temporary change, finalize after jq's changes go in
458 public void close() {
459 super.close();
460 if (mHistoryCursor != null) {
461 mHistoryCursor.close();
462 mHistoryCursor = null;
463 }
464 if (mSuggestCursor != null) {
465 mSuggestCursor.close();
466 mSuggestCursor = null;
467 }
468 }
Mike LeBeau21beb132009-05-13 14:57:50 -0700469
470 /**
471 * Provides the title (text line 1) for a browser suggestion, which should be the
472 * webpage title. If the webpage title is empty, returns the stripped url instead.
473 *
Mike LeBeau21beb132009-05-13 14:57:50 -0700474 * @return the title string to use
475 */
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700476 private String getHistoryTitle() {
477 String title = mHistoryCursor.getString(2 /* webpage title */);
Mike LeBeau21beb132009-05-13 14:57:50 -0700478 if (TextUtils.isEmpty(title) || TextUtils.getTrimmedLength(title) == 0) {
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700479 title = beautifyUrl(mHistoryCursor.getString(1 /* url */));
Mike LeBeau21beb132009-05-13 14:57:50 -0700480 }
481 return title;
482 }
483
484 /**
485 * Provides the subtitle (text line 2) for a browser suggestion, which should be the
486 * webpage url. If the webpage title is empty, then the url should go in the title
487 * instead, and the subtitle should be empty, so this would return null.
488 *
Mike LeBeau21beb132009-05-13 14:57:50 -0700489 * @return the subtitle string to use, or null if none
490 */
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700491 private String getHistorySubtitle() {
492 String title = mHistoryCursor.getString(2 /* webpage title */);
Mike LeBeau21beb132009-05-13 14:57:50 -0700493 if (TextUtils.isEmpty(title) || TextUtils.getTrimmedLength(title) == 0) {
494 return null;
495 } else {
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700496 return beautifyUrl(mHistoryCursor.getString(1 /* url */));
Mike LeBeau21beb132009-05-13 14:57:50 -0700497 }
498 }
499
500 /**
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700501 * Strips "http://" from the beginning of a url and adds html formatting to make it green.
Mike LeBeau21beb132009-05-13 14:57:50 -0700502 */
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700503 private String beautifyUrl(String url) {
Mike LeBeau21beb132009-05-13 14:57:50 -0700504 if (url.startsWith("http://")) {
505 url = url.substring(7);
506 }
Mike LeBeau1ef26a32009-05-13 20:11:00 -0700507 return "<font color=\"green\">" + url + "</font>";
Mike LeBeau21beb132009-05-13 14:57:50 -0700508 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800509 }
510
511 @Override
512 public Cursor query(Uri url, String[] projectionIn, String selection,
513 String[] selectionArgs, String sortOrder)
514 throws IllegalStateException {
515 SQLiteDatabase db = mOpenHelper.getReadableDatabase();
516
517 int match = URI_MATCHER.match(url);
518 if (match == -1) {
519 throw new IllegalArgumentException("Unknown URL");
520 }
521
Bjorn Bringert346dafb2009-04-29 21:41:47 +0100522 if (match == URI_MATCH_SUGGEST || match == URI_MATCH_BOOKMARKS_SUGGEST) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800523 String suggestSelection;
524 String [] myArgs;
525 if (selectionArgs[0] == null || selectionArgs[0].equals("")) {
526 suggestSelection = null;
527 myArgs = null;
528 } else {
529 String like = selectionArgs[0] + "%";
Leon Scrogginsfaa15db2009-04-03 10:16:06 -0700530 if (selectionArgs[0].startsWith("http")
531 || selectionArgs[0].startsWith("file")) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800532 myArgs = new String[1];
533 myArgs[0] = like;
534 suggestSelection = selection;
535 } else {
536 SUGGEST_ARGS[0] = "http://" + like;
537 SUGGEST_ARGS[1] = "http://www." + like;
538 SUGGEST_ARGS[2] = "https://" + like;
539 SUGGEST_ARGS[3] = "https://www." + like;
540 myArgs = SUGGEST_ARGS;
541 suggestSelection = SUGGEST_SELECTION;
542 }
543 }
544
545 Cursor c = db.query(TABLE_NAMES[URI_MATCH_BOOKMARKS],
546 SUGGEST_PROJECTION, suggestSelection, myArgs, null, null,
547 ORDER_BY,
548 (new Integer(MAX_SUGGESTION_LONG_ENTRIES)).toString());
549
Bjorn Bringert346dafb2009-04-29 21:41:47 +0100550 if (match == URI_MATCH_BOOKMARKS_SUGGEST
551 || Regex.WEB_URL_PATTERN.matcher(selectionArgs[0]).matches()) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800552 return new MySuggestionCursor(c, null, "");
553 } else {
554 // get Google suggest if there is still space in the list
555 if (myArgs != null && myArgs.length > 1
556 && c.getCount() < (MAX_SUGGESTION_SHORT_ENTRIES - 1)) {
Bjorn Bringert24e1ec62009-04-29 16:10:43 +0100557 // TODO: This shouldn't be hard-coded. Instead, it should use the
558 // default web search provider. But the API for that is not implemented yet.
559 ComponentName googleSearchComponent =
560 new ComponentName("com.android.googlesearch",
561 "com.android.googlesearch.GoogleSearch");
562 SearchableInfo si =
563 SearchManager.getSearchableInfo(googleSearchComponent, false);
564 Cursor sc = SearchManager.getSuggestions(getContext(), si, selectionArgs[0]);
565 return new MySuggestionCursor(c, sc, selectionArgs[0]);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800566 }
567 return new MySuggestionCursor(c, null, selectionArgs[0]);
568 }
569 }
570
571 String[] projection = null;
572 if (projectionIn != null && projectionIn.length > 0) {
573 projection = new String[projectionIn.length + 1];
574 System.arraycopy(projectionIn, 0, projection, 0, projectionIn.length);
575 projection[projectionIn.length] = "_id AS _id";
576 }
577
578 StringBuilder whereClause = new StringBuilder(256);
579 if (match == URI_MATCH_BOOKMARKS_ID || match == URI_MATCH_SEARCHES_ID) {
580 whereClause.append("(_id = ").append(url.getPathSegments().get(1))
581 .append(")");
582 }
583
584 // Tack on the user's selection, if present
585 if (selection != null && selection.length() > 0) {
586 if (whereClause.length() > 0) {
587 whereClause.append(" AND ");
588 }
589
590 whereClause.append('(');
591 whereClause.append(selection);
592 whereClause.append(')');
593 }
594 Cursor c = db.query(TABLE_NAMES[match % 10], projection,
595 whereClause.toString(), selectionArgs, null, null, sortOrder,
596 null);
597 c.setNotificationUri(getContext().getContentResolver(), url);
598 return c;
599 }
600
601 @Override
602 public String getType(Uri url) {
603 int match = URI_MATCHER.match(url);
604 switch (match) {
605 case URI_MATCH_BOOKMARKS:
606 return "vnd.android.cursor.dir/bookmark";
607
608 case URI_MATCH_BOOKMARKS_ID:
609 return "vnd.android.cursor.item/bookmark";
610
611 case URI_MATCH_SEARCHES:
612 return "vnd.android.cursor.dir/searches";
613
614 case URI_MATCH_SEARCHES_ID:
615 return "vnd.android.cursor.item/searches";
616
617 case URI_MATCH_SUGGEST:
618 return SearchManager.SUGGEST_MIME_TYPE;
619
620 default:
621 throw new IllegalArgumentException("Unknown URL");
622 }
623 }
624
625 @Override
626 public Uri insert(Uri url, ContentValues initialValues) {
627 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
628
629 int match = URI_MATCHER.match(url);
630 Uri uri = null;
631 switch (match) {
632 case URI_MATCH_BOOKMARKS: {
633 // Insert into the bookmarks table
634 long rowID = db.insert(TABLE_NAMES[URI_MATCH_BOOKMARKS], "url",
635 initialValues);
636 if (rowID > 0) {
637 uri = ContentUris.withAppendedId(Browser.BOOKMARKS_URI,
638 rowID);
639 }
640 break;
641 }
642
643 case URI_MATCH_SEARCHES: {
644 // Insert into the searches table
645 long rowID = db.insert(TABLE_NAMES[URI_MATCH_SEARCHES], "url",
646 initialValues);
647 if (rowID > 0) {
648 uri = ContentUris.withAppendedId(Browser.SEARCHES_URI,
649 rowID);
650 }
651 break;
652 }
653
654 default:
655 throw new IllegalArgumentException("Unknown URL");
656 }
657
658 if (uri == null) {
659 throw new IllegalArgumentException("Unknown URL");
660 }
661 getContext().getContentResolver().notifyChange(uri, null);
662 return uri;
663 }
664
665 @Override
666 public int delete(Uri url, String where, String[] whereArgs) {
667 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
668
669 int match = URI_MATCHER.match(url);
670 if (match == -1 || match == URI_MATCH_SUGGEST) {
671 throw new IllegalArgumentException("Unknown URL");
672 }
673
674 if (match == URI_MATCH_BOOKMARKS_ID || match == URI_MATCH_SEARCHES_ID) {
675 StringBuilder sb = new StringBuilder();
676 if (where != null && where.length() > 0) {
677 sb.append("( ");
678 sb.append(where);
679 sb.append(" ) AND ");
680 }
681 sb.append("_id = ");
682 sb.append(url.getPathSegments().get(1));
683 where = sb.toString();
684 }
685
686 int count = db.delete(TABLE_NAMES[match % 10], where, whereArgs);
687 getContext().getContentResolver().notifyChange(url, null);
688 return count;
689 }
690
691 @Override
692 public int update(Uri url, ContentValues values, String where,
693 String[] whereArgs) {
694 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
695
696 int match = URI_MATCHER.match(url);
697 if (match == -1 || match == URI_MATCH_SUGGEST) {
698 throw new IllegalArgumentException("Unknown URL");
699 }
700
701 if (match == URI_MATCH_BOOKMARKS_ID || match == URI_MATCH_SEARCHES_ID) {
702 StringBuilder sb = new StringBuilder();
703 if (where != null && where.length() > 0) {
704 sb.append("( ");
705 sb.append(where);
706 sb.append(" ) AND ");
707 }
708 sb.append("_id = ");
709 sb.append(url.getPathSegments().get(1));
710 where = sb.toString();
711 }
712
713 int ret = db.update(TABLE_NAMES[match % 10], values, where, whereArgs);
714 getContext().getContentResolver().notifyChange(url, null);
715 return ret;
716 }
717}