1/*
2 * Copyright (C) 2010 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 android.provider;
18
19import android.accounts.Account;
20import android.content.ContentProviderClient;
21import android.content.ContentProviderOperation;
22import android.content.ContentResolver;
23import android.content.ContentUris;
24import android.content.ContentValues;
25import android.content.Context;
26import android.database.Cursor;
27import android.graphics.BitmapFactory;
28import android.net.Uri;
29import android.os.RemoteException;
30import android.util.Pair;
31
32/**
33 * <p>
34 * The contract between the browser provider and applications. Contains the definition
35 * for the supported URIS and columns.
36 * </p>
37 * <h3>Overview</h3>
38 * <p>
39 * BrowserContract defines an database of browser-related information which are bookmarks,
40 * history, images and the mapping between the image and URL.
41 * </p>
42 * @hide
43 */
44public class BrowserContract {
45    /** The authority for the browser provider */
46    public static final String AUTHORITY = "com.android.browser";
47
48    /** A content:// style uri to the authority for the browser provider */
49    public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
50
51    /**
52     * An optional insert, update or delete URI parameter that allows the caller
53     * to specify that it is a sync adapter. The default value is false. If true
54     * the dirty flag is not automatically set and the "syncToNetwork" parameter
55     * is set to false when calling
56     * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}.
57     * @hide
58     */
59    public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
60
61    /**
62     * A parameter for use when querying any table that allows specifying a limit on the number
63     * of rows returned.
64     * @hide
65     */
66    public static final String PARAM_LIMIT = "limit";
67
68    /**
69     * Generic columns for use by sync adapters. The specific functions of
70     * these columns are private to the sync adapter. Other clients of the API
71     * should not attempt to either read or write these columns.
72     *
73     * @hide
74     */
75    interface BaseSyncColumns {
76        /** Generic column for use by sync adapters. */
77        public static final String SYNC1 = "sync1";
78        /** Generic column for use by sync adapters. */
79        public static final String SYNC2 = "sync2";
80        /** Generic column for use by sync adapters. */
81        public static final String SYNC3 = "sync3";
82        /** Generic column for use by sync adapters. */
83        public static final String SYNC4 = "sync4";
84        /** Generic column for use by sync adapters. */
85        public static final String SYNC5 = "sync5";
86    }
87
88    /**
89     * Convenience definitions for use in implementing chrome bookmarks sync in the Bookmarks table.
90     * @hide
91     */
92    public static final class ChromeSyncColumns {
93        private ChromeSyncColumns() {}
94
95        /** The server unique ID for an item */
96        public static final String SERVER_UNIQUE = BaseSyncColumns.SYNC3;
97
98        public static final String FOLDER_NAME_ROOT = "google_chrome";
99        public static final String FOLDER_NAME_BOOKMARKS = "google_chrome_bookmarks";
100        public static final String FOLDER_NAME_BOOKMARKS_BAR = "bookmark_bar";
101        public static final String FOLDER_NAME_OTHER_BOOKMARKS = "other_bookmarks";
102
103        /** The client unique ID for an item */
104        public static final String CLIENT_UNIQUE = BaseSyncColumns.SYNC4;
105    }
106
107    /**
108     * Columns that appear when each row of a table belongs to a specific
109     * account, including sync information that an account may need.
110     * @hide
111     */
112    interface SyncColumns extends BaseSyncColumns {
113        /**
114         * The name of the account instance to which this row belongs, which when paired with
115         * {@link #ACCOUNT_TYPE} identifies a specific account.
116         * <P>Type: TEXT</P>
117         */
118        public static final String ACCOUNT_NAME = "account_name";
119
120        /**
121         * The type of account to which this row belongs, which when paired with
122         * {@link #ACCOUNT_NAME} identifies a specific account.
123         * <P>Type: TEXT</P>
124         */
125        public static final String ACCOUNT_TYPE = "account_type";
126
127        /**
128         * String that uniquely identifies this row to its source account.
129         * <P>Type: TEXT</P>
130         */
131        public static final String SOURCE_ID = "sourceid";
132
133        /**
134         * Version number that is updated whenever this row or its related data
135         * changes.
136         * <P>Type: INTEGER</P>
137         */
138        public static final String VERSION = "version";
139
140        /**
141         * Flag indicating that {@link #VERSION} has changed, and this row needs
142         * to be synchronized by its owning account.
143         * <P>Type: INTEGER (boolean)</P>
144         */
145        public static final String DIRTY = "dirty";
146
147        /**
148         * The time that this row was last modified by a client (msecs since the epoch).
149         * <P>Type: INTEGER</P>
150         */
151        public static final String DATE_MODIFIED = "modified";
152    }
153
154    interface CommonColumns {
155        /**
156         * The unique ID for a row.
157         * <P>Type: INTEGER (long)</P>
158         */
159        public static final String _ID = "_id";
160
161        /**
162         * This column is valid when the row is a URL. The history table's URL
163         * can not be updated.
164         * <P>Type: TEXT (URL)</P>
165         */
166        public static final String URL = "url";
167
168        /**
169         * The user visible title.
170         * <P>Type: TEXT</P>
171         */
172        public static final String TITLE = "title";
173
174        /**
175         * The time that this row was created on its originating client (msecs
176         * since the epoch).
177         * <P>Type: INTEGER</P>
178         * @hide
179         */
180        public static final String DATE_CREATED = "created";
181    }
182
183    /**
184     * @hide
185     */
186    interface ImageColumns {
187        /**
188         * The favicon of the bookmark, may be NULL.
189         * Must decode via {@link BitmapFactory#decodeByteArray}.
190         * <p>Type: BLOB (image)</p>
191         */
192        public static final String FAVICON = "favicon";
193
194        /**
195         * A thumbnail of the page,may be NULL.
196         * Must decode via {@link BitmapFactory#decodeByteArray}.
197         * <p>Type: BLOB (image)</p>
198         */
199        public static final String THUMBNAIL = "thumbnail";
200
201        /**
202         * The touch icon for the web page, may be NULL.
203         * Must decode via {@link BitmapFactory#decodeByteArray}.
204         * <p>Type: BLOB (image)</p>
205         */
206        public static final String TOUCH_ICON = "touch_icon";
207    }
208
209    interface HistoryColumns {
210        /**
211         * The date the item was last visited, in milliseconds since the epoch.
212         * <p>Type: INTEGER (date in milliseconds since January 1, 1970)</p>
213         */
214        public static final String DATE_LAST_VISITED = "date";
215
216        /**
217         * The number of times the item has been visited.
218         * <p>Type: INTEGER</p>
219         */
220        public static final String VISITS = "visits";
221
222        /**
223         * @hide
224         */
225        public static final String USER_ENTERED = "user_entered";
226    }
227
228    interface ImageMappingColumns {
229        /**
230         * The ID of the image in Images. One image can map onto the multiple URLs.
231         * <P>Type: INTEGER (long)</P>
232         */
233        public static final String IMAGE_ID = "image_id";
234
235        /**
236         * The URL. The URL can map onto the different type of images.
237         * <P>Type: TEXT (URL)</P>
238         */
239        public static final String URL = "url";
240    }
241
242    /**
243     * The bookmarks table, which holds the user's browser bookmarks.
244     */
245    public static final class Bookmarks implements CommonColumns, ImageColumns, SyncColumns {
246        /**
247         * This utility class cannot be instantiated.
248         */
249        private Bookmarks() {}
250
251        /**
252         * The content:// style URI for this table
253         */
254        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "bookmarks");
255
256        /**
257         * Used in {@link Bookmarks#TYPE} column and indicats the row is a bookmark.
258         */
259        public static final int BOOKMARK_TYPE_BOOKMARK = 1;
260
261        /**
262         * Used in {@link Bookmarks#TYPE} column and indicats the row is a folder.
263         */
264        public static final int BOOKMARK_TYPE_FOLDER = 2;
265
266        /**
267         * Used in {@link Bookmarks#TYPE} column and indicats the row is the bookmark bar folder.
268         */
269        public static final int BOOKMARK_TYPE_BOOKMARK_BAR_FOLDER = 3;
270
271        /**
272         * Used in {@link Bookmarks#TYPE} column and indicats the row is other folder and
273         */
274        public static final int BOOKMARK_TYPE_OTHER_FOLDER = 4;
275
276        /**
277         * Used in {@link Bookmarks#TYPE} column and indicats the row is other folder, .
278         */
279        public static final int BOOKMARK_TYPE_MOBILE_FOLDER = 5;
280
281        /**
282         * The type of the item.
283         * <P>Type: INTEGER</P>
284         * <p>Allowed values are:</p>
285         * <p>
286         * <ul>
287         * <li>{@link #BOOKMARK_TYPE_BOOKMARK}</li>
288         * <li>{@link #BOOKMARK_TYPE_FOLDER}</li>
289         * <li>{@link #BOOKMARK_TYPE_BOOKMARK_BAR_FOLDER}</li>
290         * <li>{@link #BOOKMARK_TYPE_OTHER_FOLDER}</li>
291         * <li>{@link #BOOKMARK_TYPE_MOBILE_FOLDER}</li>
292         * </ul>
293         * </p>
294         * <p> The TYPE_BOOKMARK_BAR_FOLDER, TYPE_OTHER_FOLDER and TYPE_MOBILE_FOLDER
295         * can not be updated or deleted.</p>
296         */
297        public static final String TYPE = "type";
298
299        /**
300         * The content:// style URI for the default folder
301         * @hide
302         */
303        public static final Uri CONTENT_URI_DEFAULT_FOLDER =
304                Uri.withAppendedPath(CONTENT_URI, "folder");
305
306        /**
307         * Query parameter used to specify an account name
308         * @hide
309         */
310        public static final String PARAM_ACCOUNT_NAME = "acct_name";
311
312        /**
313         * Query parameter used to specify an account type
314         * @hide
315         */
316        public static final String PARAM_ACCOUNT_TYPE = "acct_type";
317
318        /**
319         * Builds a URI that points to a specific folder.
320         * @param folderId the ID of the folder to point to
321         * @hide
322         */
323        public static final Uri buildFolderUri(long folderId) {
324            return ContentUris.withAppendedId(CONTENT_URI_DEFAULT_FOLDER, folderId);
325        }
326
327        /**
328         * The MIME type of {@link #CONTENT_URI} providing a directory of bookmarks.
329         */
330        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/bookmark";
331
332        /**
333         * The MIME type of a {@link #CONTENT_URI} of a single bookmark.
334         */
335        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/bookmark";
336
337        /**
338         * Query parameter to use if you want to see deleted bookmarks that are still
339         * around on the device and haven't been synced yet.
340         * @see #IS_DELETED
341         * @hide
342         */
343        public static final String QUERY_PARAMETER_SHOW_DELETED = "show_deleted";
344
345        /**
346         * Flag indicating if an item is a folder or bookmark. Non-zero values indicate
347         * a folder and zero indicates a bookmark.
348         * <P>Type: INTEGER (boolean)</P>
349         * @hide
350         */
351        public static final String IS_FOLDER = "folder";
352
353        /**
354         * The ID of the parent folder. ID 0 is the root folder.
355         * <P>Type: INTEGER (reference to item in the same table)</P>
356         */
357        public static final String PARENT = "parent";
358
359        /**
360         * The source ID for an item's parent. Read-only.
361         * @see #PARENT
362         * @hide
363         */
364        public static final String PARENT_SOURCE_ID = "parent_source";
365
366        /**
367         * The position of the bookmark in relation to it's siblings that share the same
368         * {@link #PARENT}. May be negative.
369         * <P>Type: INTEGER</P>
370         * @hide
371         */
372        public static final String POSITION = "position";
373
374        /**
375         * The item that the bookmark should be inserted after.
376         * May be negative.
377         * <P>Type: INTEGER</P>
378         * @hide
379         */
380        public static final String INSERT_AFTER = "insert_after";
381
382        /**
383         * The source ID for the item that the bookmark should be inserted after. Read-only.
384         * May be negative.
385         * <P>Type: INTEGER</P>
386         * @see #INSERT_AFTER
387         * @hide
388         */
389        public static final String INSERT_AFTER_SOURCE_ID = "insert_after_source";
390
391        /**
392         * A flag to indicate if an item has been deleted. Queries will not return deleted
393         * entries unless you add the {@link #QUERY_PARAMETER_SHOW_DELETED} query paramter
394         * to the URI when performing your query.
395         * <p>Type: INTEGER (non-zero if the item has been deleted, zero if it hasn't)
396         * @see #QUERY_PARAMETER_SHOW_DELETED
397         * @hide
398         */
399        public static final String IS_DELETED = "deleted";
400    }
401
402    /**
403     * Read-only table that lists all the accounts that are used to provide bookmarks.
404     * @hide
405     */
406    public static final class Accounts {
407        /**
408         * Directory under {@link Bookmarks#CONTENT_URI}
409         */
410        public static final Uri CONTENT_URI =
411                AUTHORITY_URI.buildUpon().appendPath("accounts").build();
412
413        /**
414         * The name of the account instance to which this row belongs, which when paired with
415         * {@link #ACCOUNT_TYPE} identifies a specific account.
416         * <P>Type: TEXT</P>
417         */
418        public static final String ACCOUNT_NAME = "account_name";
419
420        /**
421         * The type of account to which this row belongs, which when paired with
422         * {@link #ACCOUNT_NAME} identifies a specific account.
423         * <P>Type: TEXT</P>
424         */
425        public static final String ACCOUNT_TYPE = "account_type";
426
427        /**
428         * The ID of the account's root folder. This will be the ID of the folder
429         * returned when querying {@link Bookmarks#CONTENT_URI_DEFAULT_FOLDER}.
430         * <P>Type: INTEGER</P>
431         */
432        public static final String ROOT_ID = "root_id";
433    }
434
435    /**
436     * The history table, which holds the browsing history.
437     */
438    public static final class History implements CommonColumns, HistoryColumns, ImageColumns {
439        /**
440         * This utility class cannot be instantiated.
441         */
442        private History() {}
443
444        /**
445         * The content:// style URI for this table
446         */
447        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "history");
448
449        /**
450         * The MIME type of {@link #CONTENT_URI} providing a directory of browser history items.
451         */
452        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/browser-history";
453
454        /**
455         * The MIME type of a {@link #CONTENT_URI} of a single browser history item.
456         */
457        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/browser-history";
458    }
459
460    /**
461     * The search history table.
462     * @hide
463     */
464    public static final class Searches {
465        private Searches() {}
466
467        /**
468         * The content:// style URI for this table
469         */
470        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "searches");
471
472        /**
473         * The MIME type of {@link #CONTENT_URI} providing a directory of browser search items.
474         */
475        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/searches";
476
477        /**
478         * The MIME type of a {@link #CONTENT_URI} of a single browser search item.
479         */
480        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/searches";
481
482        /**
483         * The unique ID for a row.
484         * <P>Type: INTEGER (long)</P>
485         */
486        public static final String _ID = "_id";
487
488        /**
489         * The user entered search term.
490         */
491        public static final String SEARCH = "search";
492
493        /**
494         * The date the search was performed, in milliseconds since the epoch.
495         * <p>Type: NUMBER (date in milliseconds since January 1, 1970)</p>
496         */
497        public static final String DATE = "date";
498    }
499
500    /**
501     * A table provided for sync adapters to use for storing private sync state data.
502     *
503     * @see SyncStateContract
504     * @hide
505     */
506    public static final class SyncState implements SyncStateContract.Columns {
507        /**
508         * This utility class cannot be instantiated
509         */
510        private SyncState() {}
511
512        public static final String CONTENT_DIRECTORY =
513                SyncStateContract.Constants.CONTENT_DIRECTORY;
514
515        /**
516         * The content:// style URI for this table
517         */
518        public static final Uri CONTENT_URI =
519                Uri.withAppendedPath(AUTHORITY_URI, CONTENT_DIRECTORY);
520
521        /**
522         * @see android.provider.SyncStateContract.Helpers#get
523         */
524        public static byte[] get(ContentProviderClient provider, Account account)
525                throws RemoteException {
526            return SyncStateContract.Helpers.get(provider, CONTENT_URI, account);
527        }
528
529        /**
530         * @see android.provider.SyncStateContract.Helpers#get
531         */
532        public static Pair<Uri, byte[]> getWithUri(ContentProviderClient provider, Account account)
533                throws RemoteException {
534            return SyncStateContract.Helpers.getWithUri(provider, CONTENT_URI, account);
535        }
536
537        /**
538         * @see android.provider.SyncStateContract.Helpers#set
539         */
540        public static void set(ContentProviderClient provider, Account account, byte[] data)
541                throws RemoteException {
542            SyncStateContract.Helpers.set(provider, CONTENT_URI, account, data);
543        }
544
545        /**
546         * @see android.provider.SyncStateContract.Helpers#newSetOperation
547         */
548        public static ContentProviderOperation newSetOperation(Account account, byte[] data) {
549            return SyncStateContract.Helpers.newSetOperation(CONTENT_URI, account, data);
550        }
551    }
552
553    /**
554     * <p>
555     * Stores images for URLs.
556     * </p>
557     * <p>
558     * The rows in this table can not be updated since there might have multiple URLs mapping onto
559     * the same image. If you want to update a URL's image, you need to add the new image in this
560     * table, then update the mapping onto the added image.
561     * </p>
562     * <p>
563     * Every image should be at least associated with one URL, otherwise it will be removed after a
564     * while.
565     * </p>
566     */
567    public static final class Images implements ImageColumns {
568        /**
569         * This utility class cannot be instantiated
570         */
571        private Images() {}
572
573        /**
574         * The content:// style URI for this table
575         */
576        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "images");
577
578        /**
579         * The MIME type of {@link #CONTENT_URI} providing a directory of images.
580         */
581        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/images";
582
583        /**
584         * The MIME type of a {@link #CONTENT_URI} of a single image.
585         */
586        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/images";
587
588        /**
589         * Used in {@link Images#TYPE} column and indicats the row is a favicon.
590         */
591        public static final int IMAGE_TYPE_FAVICON = 1;
592
593        /**
594         * Used in {@link Images#TYPE} column and indicats the row is a precomposed touch icon.
595         */
596        public static final int IMAGE_TYPE_PRECOMPOSED_TOUCH_ICON = 2;
597
598        /**
599         * Used in {@link Images#TYPE} column and indicats the row is a touch icon.
600         */
601        public static final int IMAGE_TYPE_TOUCH_ICON = 4;
602
603        /**
604         * The type of item in the table.
605         * <P>Type: INTEGER</P>
606         * <p>Allowed values are:</p>
607         * <p>
608         * <ul>
609         * <li>{@link #IMAGE_TYPE_FAVICON}</li>
610         * <li>{@link #IMAGE_TYPE_PRECOMPOSED_TOUCH_ICON}</li>
611         * <li>{@link #IMAGE_TYPE_TOUCH_ICON}</li>
612         * </ul>
613         * </p>
614         */
615        public static final String TYPE = "type";
616
617        /**
618         * The image data.
619         * <p>Type: BLOB (image)</p>
620         */
621        public static final String DATA = "data";
622
623        /**
624         * The URL the images came from.
625         * <P>Type: TEXT (URL)</P>
626         * @hide
627         */
628        public static final String URL = "url_key";
629    }
630
631    /**
632     * <p>
633     * A table that stores the mappings between the image and the URL.
634     * </p>
635     * <p>
636     * Deleting or Updating a mapping might also deletes the mapped image if there is no other URL
637     * maps onto it.
638     * </p>
639     */
640    public static final class ImageMappings implements ImageMappingColumns {
641        /**
642         * This utility class cannot be instantiated
643         */
644        private ImageMappings() {}
645
646        /**
647         * The content:// style URI for this table
648         */
649        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "image_mappings");
650
651        /**
652         * The MIME type of {@link #CONTENT_URI} providing a directory of image mappings.
653         */
654        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/image_mappings";
655
656        /**
657         * The MIME type of a {@link #CONTENT_URI} of a single image mapping.
658         */
659        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/image_mappings";
660    }
661
662    /**
663     * A combined view of bookmarks and history. All bookmarks in all folders are included and
664     * no folders are included.
665     * @hide
666     */
667    public static final class Combined implements CommonColumns, HistoryColumns, ImageColumns {
668        /**
669         * This utility class cannot be instantiated
670         */
671        private Combined() {}
672
673        /**
674         * The content:// style URI for this table
675         */
676        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "combined");
677
678        /**
679         * Flag indicating that an item is a bookmark. A value of 1 indicates a bookmark, a value
680         * of 0 indicates a history item.
681         * <p>Type: INTEGER (boolean)</p>
682         */
683        public static final String IS_BOOKMARK = "bookmark";
684    }
685
686    /**
687     * A table that stores settings specific to the browser. Only support query and insert.
688     * @hide
689     */
690    public static final class Settings {
691        /**
692         * This utility class cannot be instantiated
693         */
694        private Settings() {}
695
696        /**
697         * The content:// style URI for this table
698         */
699        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "settings");
700
701        /**
702         * Key for a setting value.
703         */
704        public static final String KEY = "key";
705
706        /**
707         * Value for a setting.
708         */
709        public static final String VALUE = "value";
710
711        /**
712         * If set to non-0 the user has opted into bookmark sync.
713         */
714        public static final String KEY_SYNC_ENABLED = "sync_enabled";
715
716        /**
717         * Returns true if bookmark sync is enabled
718         */
719        static public boolean isSyncEnabled(Context context) {
720            Cursor cursor = null;
721            try {
722                cursor = context.getContentResolver().query(CONTENT_URI, new String[] { VALUE },
723                        KEY + "=?", new String[] { KEY_SYNC_ENABLED }, null);
724                if (cursor == null || !cursor.moveToFirst()) {
725                    return false;
726                }
727                return cursor.getInt(0) != 0;
728            } finally {
729                if (cursor != null) cursor.close();
730            }
731        }
732
733        /**
734         * Sets the bookmark sync enabled setting.
735         */
736        static public void setSyncEnabled(Context context, boolean enabled) {
737            ContentValues values = new ContentValues();
738            values.put(KEY, KEY_SYNC_ENABLED);
739            values.put(VALUE, enabled ? 1 : 0);
740            context.getContentResolver().insert(CONTENT_URI, values);
741        }
742    }
743}
744