summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/browser/Controller.java63
-rw-r--r--src/com/android/browser/NavTabView.java44
-rw-r--r--src/com/android/browser/SnapshotTab.java163
-rw-r--r--src/com/android/browser/Tab.java117
-rw-r--r--src/com/android/browser/TabControl.java48
-rw-r--r--src/com/android/browser/provider/BrowserProvider2.java86
6 files changed, 367 insertions, 154 deletions
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index efd9012..faee0c7 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -23,6 +23,7 @@ import android.content.ClipboardManager;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
+import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@@ -78,6 +79,7 @@ import android.widget.Toast;
import com.android.browser.IntentHandler.UrlData;
import com.android.browser.UI.DropdownChangeListener;
import com.android.browser.provider.BrowserProvider;
+import com.android.browser.provider.BrowserProvider2.Snapshots;
import com.android.browser.search.SearchEngine;
import com.android.common.Search;
@@ -326,6 +328,8 @@ public class Controller
webView.setInitialScale(scale);
}
}
+ mTabControl.loadSnapshotTabs();
+ mUi.updateTabs(mTabControl.getTabs());
} else {
mTabControl.restoreState(icicle, currentTabId, restoreIncognitoTabs,
mUi.needsRestoreAllTabs());
@@ -797,7 +801,8 @@ public class Controller
public void onPageFinished(Tab tab) {
mUi.onTabDataChanged(tab);
if (!tab.isPrivateBrowsingEnabled()
- && !TextUtils.isEmpty(tab.getUrl())) {
+ && !TextUtils.isEmpty(tab.getUrl())
+ && !tab.isSnapshot()) {
if (tab.inForeground() && !didUserStopLoading()
|| !tab.inForeground()) {
// Only update the bookmark screenshot if the user did not
@@ -1605,19 +1610,28 @@ public class Controller
// TODO: Show error messages
Tab source = getTabControl().getCurrentTab();
if (source == null) break;
- Tab snapshot = createNewTab(false, false, false);
- if (snapshot == null) break;
- try {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- source.saveSnapshot(bos);
- ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
- snapshot.loadSnapshot(bis);
- mUi.onTabDataChanged(snapshot);
- bis.close();
- bos.close();
- setActiveTab(snapshot);
- } catch (IOException e) {
- }
+ final ContentResolver cr = mActivity.getContentResolver();
+ final ContentValues values = source.createSnapshotValues();
+ new AsyncTask<Tab, Void, Long>() {
+ @Override
+ protected Long doInBackground(Tab... params) {
+ Tab t = params[0];
+ if (values == null) {
+ return t.isSnapshot()
+ ? ((SnapshotTab)t).getSnapshotId()
+ : -1;
+ }
+ Uri result = cr.insert(Snapshots.CONTENT_URI, values);
+ long id = ContentUris.parseId(result);
+ return id;
+ }
+
+ protected void onPostExecute(Long id) {
+ if (id > 0) {
+ createNewSnapshotTab(id, true);
+ }
+ };
+ }.execute(source);
break;
case R.id.save_webarchive_menu_id:
@@ -2139,6 +2153,18 @@ public class Controller
mUi.removeTab(tab);
mTabControl.removeTab(tab);
mCrashRecoveryHandler.backupState();
+ if (tab.isSnapshot()) {
+ SnapshotTab st = (SnapshotTab) tab;
+ final Uri uri = ContentUris.withAppendedId(
+ Snapshots.CONTENT_URI, st.getSnapshotId());
+ final ContentResolver cr = mActivity.getContentResolver();
+ new Thread() {
+ @Override
+ public void run() {
+ cr.delete(uri, null, null);
+ }
+ }.start();
+ }
}
@Override
@@ -2281,6 +2307,15 @@ public class Controller
return tab;
}
+ private SnapshotTab createNewSnapshotTab(long snapshotId, boolean setActive) {
+ SnapshotTab tab = mTabControl.createSnapshotTab(snapshotId);
+ addTab(tab);
+ if (setActive) {
+ setActiveTab(tab);
+ }
+ return tab;
+ }
+
/**
* @param tab the tab to switch to
* @return boolean True if we successfully switched to a different tab. If
diff --git a/src/com/android/browser/NavTabView.java b/src/com/android/browser/NavTabView.java
index f170b0f..daa5013 100644
--- a/src/com/android/browser/NavTabView.java
+++ b/src/com/android/browser/NavTabView.java
@@ -49,7 +49,6 @@ public class NavTabView extends LinearLayout {
private Drawable mUrlBg;
private float mMediumTextSize;
private float mSmallTextSize;
- private boolean mPaused;
public NavTabView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
@@ -85,20 +84,6 @@ public class NavTabView extends LinearLayout {
setState(false);
}
- protected void pause() {
- mPaused = true;
- mWebView.onPause();
- }
-
- protected void resume() {
- mPaused = false;
- mWebView.onResume();
- }
-
- protected boolean isPaused() {
- return mPaused;
- }
-
protected boolean isRefresh(View v) {
return v == mRefresh;
}
@@ -128,10 +113,8 @@ public class NavTabView extends LinearLayout {
private void setState(boolean highlighted) {
if (highlighted) {
setAlpha(1.0f);
- mRefresh.setVisibility(View.VISIBLE);
mFavicon.setVisibility(View.VISIBLE);
- mForward.setVisibility(mWebView.canGoForward()
- ? View.VISIBLE : View.GONE);
+ setupButtons();
mTitleBar.setBackgroundDrawable(mTitleBg);
mClose.setVisibility(View.VISIBLE);
mTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, mMediumTextSize);
@@ -166,18 +149,27 @@ public class NavTabView extends LinearLayout {
protected void setWebView(PhoneUi ui, Tab tab) {
mTab = tab;
+ mFavicon.setImageDrawable(ui.getFaviconDrawable(tab.getFavicon()));
+ setTitle();
BrowserWebView web = (BrowserWebView) tab.getWebView();
- if (web == null) return;
- mWebView = web;
- removeFromParent(mWebView);
- mProxy = new WebProxyView(mContext, mWebView);
- mContainer.addView(mProxy, 0);
- if (mWebView != null) {
+ if (web != null) {
+ mWebView = web;
+ removeFromParent(mWebView);
+ mProxy = new WebProxyView(mContext, mWebView);
+ mContainer.addView(mProxy, 0);
+ }
+ setupButtons();
+ }
+
+ void setupButtons() {
+ if (mTab.isSnapshot()) {
+ mForward.setVisibility(View.GONE);
+ mRefresh.setVisibility(View.GONE);
+ } else if (mWebView != null) {
mForward.setVisibility(mWebView.canGoForward()
? View.VISIBLE : View.GONE);
+ mRefresh.setVisibility(View.VISIBLE);
}
- mFavicon.setImageDrawable(ui.getFaviconDrawable(tab.getFavicon()));
- setTitle();
}
protected void hideTitle() {
diff --git a/src/com/android/browser/SnapshotTab.java b/src/com/android/browser/SnapshotTab.java
new file mode 100644
index 0000000..52a5c5f
--- /dev/null
+++ b/src/com/android/browser/SnapshotTab.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.browser;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.webkit.WebView;
+
+import com.android.browser.provider.BrowserProvider2.Snapshots;
+
+import java.io.ByteArrayInputStream;
+
+
+public class SnapshotTab extends Tab {
+
+ private long mSnapshotId;
+ private LoadData mLoadTask;
+ private WebViewFactory mWebViewFactory;
+ // TODO: Support non-persistent webview's on phone
+ private boolean mPersistentWebview;
+ private int mBackgroundColor;
+
+ public SnapshotTab(WebViewController wvcontroller, long snapshotId) {
+ super(wvcontroller, null);
+ mSnapshotId = snapshotId;
+ mWebViewFactory = mWebViewController.getWebViewFactory();
+ mPersistentWebview = !BrowserActivity.isTablet(wvcontroller.getActivity());
+ if (mPersistentWebview) {
+ WebView web = mWebViewFactory.createWebView(false);
+ setWebView(web);
+ }
+ loadData();
+ }
+
+ @Override
+ void putInForeground() {
+ if (getWebView() == null) {
+ WebView web = mWebViewFactory.createWebView(false);
+ if (mBackgroundColor != 0) {
+ web.setBackgroundColor(mBackgroundColor);
+ }
+ setWebView(web);
+ loadData();
+ }
+ super.putInForeground();
+ }
+
+ @Override
+ void putInBackground() {
+ if (getWebView() == null) return;
+ super.putInBackground();
+ if (!mPersistentWebview) {
+ super.destroy();
+ }
+ }
+
+ void loadData() {
+ if (mLoadTask == null) {
+ mLoadTask = new LoadData(this, mActivity.getContentResolver());
+ mLoadTask.execute();
+ }
+ }
+
+ @Override
+ void addChildTab(Tab child) {
+ throw new IllegalStateException("Snapshot tabs cannot have child tabs!");
+ }
+
+ @Override
+ public boolean isSnapshot() {
+ return true;
+ }
+
+ public long getSnapshotId() {
+ return mSnapshotId;
+ }
+
+ @Override
+ public ContentValues createSnapshotValues() {
+ return null;
+ }
+
+ @Override
+ boolean saveState() {
+ return false;
+ }
+
+ static class LoadData extends AsyncTask<Void, Void, Cursor> {
+
+ static final String[] PROJECTION = new String[] {
+ Snapshots._ID, // 0
+ Snapshots.TITLE, // 1
+ Snapshots.URL, // 2
+ Snapshots.FAVICON, // 3
+ Snapshots.VIEWSTATE, // 4
+ Snapshots.BACKGROUND, // 5
+ };
+
+ private SnapshotTab mTab;
+ private ContentResolver mContentResolver;
+
+ public LoadData(SnapshotTab t, ContentResolver cr) {
+ mTab = t;
+ mContentResolver = cr;
+ }
+
+ @Override
+ protected Cursor doInBackground(Void... params) {
+ long id = mTab.mSnapshotId;
+ Uri uri = ContentUris.withAppendedId(Snapshots.CONTENT_URI, id);
+ return mContentResolver.query(uri, PROJECTION, null, null, null);
+ }
+
+ @Override
+ protected void onPostExecute(Cursor result) {
+ try {
+ if (result.moveToFirst()) {
+ mTab.mCurrentState.mTitle = result.getString(1);
+ mTab.mCurrentState.mUrl = result.getString(2);
+ byte[] favicon = result.getBlob(3);
+ if (favicon != null) {
+ mTab.mCurrentState.mFavicon = BitmapFactory
+ .decodeByteArray(favicon, 0, favicon.length);
+ }
+ WebView web = mTab.getWebView();
+ if (web != null) {
+ byte[] data = result.getBlob(4);
+ ByteArrayInputStream stream = new ByteArrayInputStream(data);
+ web.loadViewState(stream);
+ }
+ mTab.mBackgroundColor = result.getInt(5);
+ mTab.mWebViewController.onPageFinished(mTab);
+ }
+ } finally {
+ if (result != null) {
+ result.close();
+ }
+ mTab.mLoadTask = null;
+ }
+ }
+
+ }
+}
diff --git a/src/com/android/browser/Tab.java b/src/com/android/browser/Tab.java
index 89f567b..bb200d8 100644
--- a/src/com/android/browser/Tab.java
+++ b/src/com/android/browser/Tab.java
@@ -20,6 +20,8 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.app.SearchManager;
import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
@@ -62,6 +64,7 @@ import android.widget.TextView;
import android.widget.Toast;
import com.android.browser.homepages.HomeProvider;
+import com.android.browser.provider.BrowserProvider2.Snapshots;
import com.android.common.speech.LoggingEvents;
import java.io.ByteArrayOutputStream;
@@ -96,10 +99,10 @@ class Tab {
}
Activity mActivity;
- private WebViewController mWebViewController;
+ protected WebViewController mWebViewController;
// The tab ID
- private long mId;
+ private long mId = -1;
// The Geolocation permissions prompt
private GeolocationPermissionsPrompt mGeolocationPermissionsPrompt;
@@ -145,7 +148,6 @@ class Tab {
private DataController mDataController;
// State of the auto-login request.
private DeviceAccountLogin mDeviceAccountLogin;
- private boolean mIsSnapshot = false;
// AsyncTask for downloading touch icons
DownloadTouchIcon mTouchIconLoader;
@@ -154,7 +156,7 @@ class Tab {
private BrowserSettings mSettings;
// All the state needed for a page
- private static class PageState {
+ protected static class PageState {
String mUrl;
String mTitle;
LockIcon mLockIcon;
@@ -192,7 +194,7 @@ class Tab {
}
// The current/loading page's state
- private PageState mCurrentState;
+ protected PageState mCurrentState;
// Used for saving and restoring each Tab
static final String ID = "ID";
@@ -1512,10 +1514,6 @@ class Tab {
* @param child the Tab that was created from this Tab
*/
void addChildTab(Tab child) {
- if (mIsSnapshot) {
- throw new IllegalStateException(
- "Snapshot tabs cannot have child tabs!");
- }
if (mChildren == null) {
mChildren = new Vector<Tab>();
}
@@ -1846,100 +1844,23 @@ class Tab {
}
public boolean isSnapshot() {
- return mIsSnapshot;
- }
-
- public boolean loadSnapshot(InputStream rstream) {
- if (rstream == null) {
- mIsSnapshot = false;
- if (mMainView != null) {
- mMainView.clearViewState();
- }
- return true;
- }
- DataInputStream stream = new DataInputStream(rstream);
- if (!readTabInfo(stream)) {
- return false;
- }
- if (!mMainView.loadViewState(stream)) {
- return false;
- }
- mIsSnapshot = true;
- return true;
- }
-
- public boolean saveSnapshot(OutputStream rstream) {
- if (rstream == null) return false;
- if (mMainView == null) return false;
- DataOutputStream stream = new DataOutputStream(rstream);
- if (saveTabInfo(stream)) {
- return mMainView.saveViewState(stream);
- }
return false;
}
- private boolean readTabInfo(DataInputStream stream) {
- try {
- PageState state = new PageState(mActivity, false);
- state.mTitle = stream.readUTF();
- if (state.mTitle.length() == 0) {
- state.mTitle = null;
- }
- state.mUrl = stream.readUTF();
- int faviconLen = stream.readInt();
- if (faviconLen > 0) {
- byte[] data = new byte[faviconLen];
- int read = stream.read(data);
- if (read != faviconLen) {
- throw new IOException("Read didn't match expected len!"
- + " Expected: " + faviconLen
- + " Got: " + read);
- }
- state.mFavicon = BitmapFactory.decodeByteArray(data, 0, data.length);
- }
- mCurrentState = state;
- return true;
- } catch (IOException e) {
- return false;
- }
- }
-
- private boolean saveTabInfo(DataOutputStream stream) {
- try {
- // mTitle might be null, but writeUTF doesn't handle that
- String title = mCurrentState.mTitle;
- stream.writeUTF(title != null ? title : "");
- // mUrl is never null
- stream.writeUTF(mCurrentState.mUrl);
- byte[] compressedPixels = compressFavicon();
- if (compressedPixels == null) {
- stream.writeInt(-1);
- } else {
- stream.writeInt(compressedPixels.length);
- stream.write(compressedPixels);
- }
- return true;
- } catch (Exception e) {
- Log.w(LOGTAG, "Failed to saveTabInfo", e);
- return false;
- }
- }
-
- private byte[] compressFavicon() {
- Bitmap favicon = mCurrentState.mFavicon;
- if (favicon == null) {
+ public ContentValues createSnapshotValues() {
+ if (mMainView == null) return null;
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ if (!mMainView.saveViewState(stream)) {
return null;
}
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- byte[] data = null;
- try {
- favicon.compress(CompressFormat.PNG, 100, stream);
- data = stream.toByteArray();
- stream.close();
- } catch (IOException e) {
- // Will return null below then
- }
- return data;
+ byte[] data = stream.toByteArray();
+ ContentResolver cr = mActivity.getContentResolver();
+ ContentValues values = new ContentValues();
+ values.put(Snapshots.TITLE, mCurrentState.mTitle);
+ values.put(Snapshots.URL, mCurrentState.mUrl);
+ values.put(Snapshots.VIEWSTATE, data);
+ values.put(Snapshots.BACKGROUND, mMainView.getPageBackgroundColor());
+ return values;
}
}
diff --git a/src/com/android/browser/TabControl.java b/src/com/android/browser/TabControl.java
index 1e21431..6566ac8 100644
--- a/src/com/android/browser/TabControl.java
+++ b/src/com/android/browser/TabControl.java
@@ -16,10 +16,14 @@
package com.android.browser;
+import android.content.ContentResolver;
+import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;
+import com.android.browser.provider.BrowserProvider2.Snapshots;
+
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
@@ -30,8 +34,8 @@ class TabControl {
// Log Tag
private static final String LOGTAG = "TabControl";
- // next Tab ID
- private static long sNextId = 0;
+ // next Tab ID, starting at 1
+ private static long sNextId = 1;
private static final String POSITIONS = "positions";
private static final String CURRENT = "current";
@@ -202,6 +206,14 @@ class TabControl {
return createNewTab(false);
}
+ SnapshotTab createSnapshotTab(long snapshotId) {
+ // TODO: Don't count this against the limit
+ SnapshotTab t = new SnapshotTab(mController, snapshotId);
+ t.setId(getNextId());
+ mTabs.add(t);
+ return t;
+ }
+
/**
* Remove the parent child relationships from all tabs.
*/
@@ -346,7 +358,10 @@ class TabControl {
}
final String idkey = Long.toString(id);
Bundle state = inState.getBundle(idkey);
- if (!restoreIncognitoTabs && state != null
+ if (state == null || state.isEmpty()) {
+ // Skip tab
+ continue;
+ } else if (!restoreIncognitoTabs
&& state.getBoolean(Tab.INCOGNITO)) {
// ignore tab
} else if (id == currentId || restoreAll) {
@@ -383,6 +398,16 @@ class TabControl {
sNextId = maxId + 1;
}
+ if (mCurrentTab == -1) {
+ if (getTabCount() > 0) {
+ setCurrentTab(getTab(0));
+ } else {
+ Tab t = createNewTab();
+ setCurrentTab(t);
+ t.getWebView().loadUrl(BrowserSettings.getInstance()
+ .getHomePage());
+ }
+ }
// restore parent/child relationships
for (long id : ids) {
final Tab tab = tabMap.get(id);
@@ -397,6 +422,21 @@ class TabControl {
}
}
}
+ loadSnapshotTabs();
+
+ }
+
+ void loadSnapshotTabs() {
+ ContentResolver cr = mController.getActivity().getContentResolver();
+ Cursor c = cr.query(Snapshots.CONTENT_URI, new String[] { "_id" },
+ null, null, null);
+ try {
+ while (c.moveToNext()) {
+ createSnapshotTab(c.getLong(0));
+ }
+ } finally {
+ c.close();
+ }
}
/**
@@ -614,7 +654,7 @@ class TabControl {
// Display the new current tab
mCurrentTab = mTabs.indexOf(newTab);
WebView mainView = newTab.getWebView();
- boolean needRestore = (mainView == null);
+ boolean needRestore = !newTab.isSnapshot() && (mainView == null);
if (needRestore) {
// Same work as in createNewTab() except don't do new Tab()
mainView = createNewWebView();
diff --git a/src/com/android/browser/provider/BrowserProvider2.java b/src/com/android/browser/provider/BrowserProvider2.java
index d9760e5..9f6e41c 100644
--- a/src/com/android/browser/provider/BrowserProvider2.java
+++ b/src/com/android/browser/provider/BrowserProvider2.java
@@ -16,15 +16,6 @@
package com.android.browser.provider;
-import com.google.common.annotations.VisibleForTesting;
-
-import com.android.browser.BookmarkUtils;
-import com.android.browser.BrowserBookmarksPage;
-import com.android.browser.R;
-import com.android.browser.UrlUtils;
-import com.android.browser.widget.BookmarkThumbnailWidgetProvider;
-import com.android.common.content.SyncStateContentProviderHelper;
-
import android.accounts.Account;
import android.app.SearchManager;
import android.content.ContentResolver;
@@ -32,7 +23,6 @@ import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.content.UriMatcher;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -45,7 +35,6 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
-import android.preference.PreferenceManager;
import android.provider.BaseColumns;
import android.provider.Browser;
import android.provider.Browser.BookmarkColumns;
@@ -63,6 +52,12 @@ import android.provider.ContactsContract.RawContacts;
import android.provider.SyncStateContract;
import android.text.TextUtils;
+import com.android.browser.R;
+import com.android.browser.UrlUtils;
+import com.android.browser.widget.BookmarkThumbnailWidgetProvider;
+import com.android.common.content.SyncStateContentProviderHelper;
+import com.google.common.annotations.VisibleForTesting;
+
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
@@ -72,6 +67,18 @@ import java.util.HashMap;
public class BrowserProvider2 extends SQLiteContentProvider {
+ public static interface Snapshots {
+
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(
+ BrowserContract.AUTHORITY_URI, "snapshots");
+ public static final String _ID = "_id";
+ public static final String VIEWSTATE = "view_state";
+ public static final String BACKGROUND = "background";
+ public static final String TITLE = History.TITLE;
+ public static final String URL = History.URL;
+ public static final String FAVICON = History.FAVICON;
+ }
+
public static final String LEGACY_AUTHORITY = "browser";
static final Uri LEGACY_AUTHORITY_URI = new Uri.Builder()
.authority(LEGACY_AUTHORITY).scheme("content").build();
@@ -82,6 +89,7 @@ public class BrowserProvider2 extends SQLiteContentProvider {
static final String TABLE_SEARCHES = "searches";
static final String TABLE_SYNC_STATE = "syncstate";
static final String TABLE_SETTINGS = "settings";
+ static final String TABLE_SNAPSHOTS = "snapshots";
static final String TABLE_BOOKMARKS_JOIN_IMAGES = "bookmarks LEFT OUTER JOIN images " +
"ON bookmarks.url = images." + Images.URL;
@@ -89,6 +97,7 @@ public class BrowserProvider2 extends SQLiteContentProvider {
"ON history.url = images." + Images.URL;
static final String VIEW_ACCOUNTS = "v_accounts";
+ static final String VIEW_SNAPSHOTS_COMBINED = "v_snapshots_combined";
static final String FORMAT_COMBINED_JOIN_SUBQUERY_JOIN_IMAGES =
"history LEFT OUTER JOIN (%s) bookmarks " +
@@ -139,6 +148,9 @@ public class BrowserProvider2 extends SQLiteContentProvider {
static final int LEGACY = 9000;
static final int LEGACY_ID = 9001;
+ static final int SNAPSHOTS = 10000;
+ static final int SNAPSHOTS_ID = 10001;
+
public static final long FIXED_ID_ROOT = 1;
// Default sort order for unsync'd bookmarks
@@ -200,6 +212,9 @@ public class BrowserProvider2 extends SQLiteContentProvider {
"bookmarks/" + SearchManager.SUGGEST_URI_PATH_QUERY,
BOOKMARKS_SUGGESTIONS);
+ matcher.addURI(authority, "snapshots", SNAPSHOTS);
+ matcher.addURI(authority, "snapshots/#", SNAPSHOTS_ID);
+
// Projection maps
HashMap<String, String> map;
@@ -333,7 +348,7 @@ public class BrowserProvider2 extends SQLiteContentProvider {
final class DatabaseHelper extends SQLiteOpenHelper {
static final String DATABASE_NAME = "browser2.db";
- static final int DATABASE_VERSION = 28;
+ static final int DATABASE_VERSION = 29;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@@ -404,6 +419,8 @@ public class BrowserProvider2 extends SQLiteContentProvider {
}
enableSync(db);
+
+ createSnapshots(db);
}
void enableSync(SQLiteDatabase db) {
@@ -500,6 +517,9 @@ public class BrowserProvider2 extends SQLiteContentProvider {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (oldVersion < 29) {
+ createSnapshots(db);
+ }
if (oldVersion < 28) {
enableSync(db);
}
@@ -520,6 +540,22 @@ public class BrowserProvider2 extends SQLiteContentProvider {
}
}
+ void createSnapshots(SQLiteDatabase db) {
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_SNAPSHOTS);
+ db.execSQL("CREATE TABLE " + TABLE_SNAPSHOTS + " (" +
+ Snapshots._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
+ Snapshots.URL + " TEXT NOT NULL," +
+ Snapshots.TITLE + " TEXT," +
+ Snapshots.BACKGROUND + " INTEGER," +
+ Snapshots.VIEWSTATE + " BLOB NOT NULL" +
+ ");");
+ db.execSQL("CREATE VIEW IF NOT EXISTS " + VIEW_SNAPSHOTS_COMBINED +
+ " AS SELECT * FROM " + TABLE_SNAPSHOTS +
+ " LEFT OUTER JOIN " + TABLE_IMAGES +
+ " ON " + TABLE_SNAPSHOTS + "." + Snapshots.URL +
+ " = images.url_key");
+ }
+
@Override
public void onOpen(SQLiteDatabase db) {
db.enableWriteAheadLogging();
@@ -970,6 +1006,17 @@ public class BrowserProvider2 extends SQLiteContentProvider {
break;
}
+ case SNAPSHOTS_ID: {
+ selection = DatabaseUtils.concatenateWhere(selection, "_id=?");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ // fall through
+ }
+ case SNAPSHOTS: {
+ qb.setTables(VIEW_SNAPSHOTS_COMBINED);
+ break;
+ }
+
default: {
throw new UnsupportedOperationException("Unknown URL " + uri.toString());
}
@@ -1169,6 +1216,16 @@ public class BrowserProvider2 extends SQLiteContentProvider {
}
break;
}
+ case SNAPSHOTS_ID: {
+ selection = DatabaseUtils.concatenateWhere(selection, TABLE_SNAPSHOTS + "._id=?");
+ selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs,
+ new String[] { Long.toString(ContentUris.parseId(uri)) });
+ // fall through
+ }
+ case SNAPSHOTS: {
+ deleted = db.delete(TABLE_SNAPSHOTS, selection, selectionArgs);
+ break;
+ }
default: {
throw new UnsupportedOperationException("Unknown delete URI " + uri);
}
@@ -1301,6 +1358,11 @@ public class BrowserProvider2 extends SQLiteContentProvider {
break;
}
+ case SNAPSHOTS: {
+ id = db.insertOrThrow(TABLE_SNAPSHOTS, Snapshots.TITLE, values);
+ break;
+ }
+
default: {
throw new UnsupportedOperationException("Unknown insert URI " + uri);
}