Skip to content

Commit

Permalink
[Offline pages] Wiring saving and opening offline page
Browse files Browse the repository at this point in the history
Changes:
1) Added the logic in EnhancedBookmarksModel to wait for OfflinePagesBridge being loaded if it is enabled
2) Supported adding a new offline page. To do this, a new asynchronous method addBookmarkAsync is added to EnhancedBookmarksModel.
3) Supported launching an offline page. getBookmarkLaunchUrl, that returns the launch url, is added to EnhancedBookmarksModel.

BUG=491352
TEST=tests added and updated

Review URL: https://codereview.chromium.org/1285313003

Cr-Commit-Position: refs/heads/master@{#343531}
  • Loading branch information
jianli-chromium authored and Commit bot committed Aug 14, 2015
1 parent 0c21d43 commit ad61982
Show file tree
Hide file tree
Showing 12 changed files with 262 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -566,13 +566,24 @@ public static boolean isEnhancedBookmarksEnabled(Profile profile) {
return nativeIsEnhancedBookmarksFeatureEnabled(profile);
}

/**
* Notifies the observer that bookmark model has been loaded.
*/
protected void notifyBookmarkModelLoaded() {
// Call isBookmarkModelLoaded() to do the check since it could be overridden by the child
// class to add the addition logic.
if (isBookmarkModelLoaded()) {
for (BookmarkModelObserver observer : mObservers) {
observer.bookmarkModelLoaded();
}
}
}

@CalledByNative
private void bookmarkModelLoaded() {
mIsNativeBookmarkModelLoaded = true;

for (BookmarkModelObserver observer : mObservers) {
observer.bookmarkModelLoaded();
}
notifyBookmarkModelLoaded();

if (!mDelayedBookmarkCallbacks.isEmpty()) {
for (int i = 0; i < mDelayedBookmarkCallbacks.size(); i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,11 @@ public abstract class ChromeSwitches {
*/
public static final String PROGRESS_BAR_ANIMATION = "progress-bar-animation";

/**
* Enable offline pages.
*/
public static final String ENABLE_OFFLINE_PAGES = "enable-offline-pages";

// Prevent instantiation.
private ChromeSwitches() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import android.content.Context;
import android.preference.PreferenceManager;
import android.support.v4.widget.DrawerLayout;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
Expand Down Expand Up @@ -410,11 +411,14 @@ public DrawerLayout getDrawerLayout() {
public void openBookmark(BookmarkId bookmark, int launchLocation) {
clearSelection();
if (mEnhancedBookmarksModel.getBookmarkById(bookmark) != null) {
String url = mEnhancedBookmarksModel.getBookmarkLaunchUrl(bookmark);
// TODO(jianli): Notify the user about the failure.
if (TextUtils.isEmpty(url)) return;

NewTabPageUma.recordAction(NewTabPageUma.ACTION_OPENED_BOOKMARK);
RecordHistogram.recordEnumeratedHistogram("Stars.LaunchLocation", launchLocation,
LaunchLocation.COUNT);
EnhancedBookmarkUtils.openBookmark(mActivity,
mEnhancedBookmarksModel.getBookmarkById(bookmark).getUrl());
EnhancedBookmarkUtils.openBookmark(mActivity, url);
finishActivityOnPhone();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.UrlConstants;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.enhancedbookmarks.EnhancedBookmarksModel.AddBookmarkCallback;
import org.chromium.chrome.browser.favicon.FaviconHelper;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.snackbar.Snackbar;
Expand Down Expand Up @@ -61,44 +62,54 @@ public static boolean isEnhancedBookmarkEnabled(Profile profile) {
* If the tab has already been bookmarked, start {@link EnhancedBookmarkEditActivity} for the
* bookmark. If not, add the bookmark to bookmarkmodel, and show a snackbar notifying the user.
*/
public static void addOrEditBookmark(long idToAdd, EnhancedBookmarksModel bookmarkModel,
public static void addOrEditBookmark(long idToAdd, final EnhancedBookmarksModel bookmarkModel,
Tab tab, final SnackbarManager snackbarManager, final Activity activity) {
if (idToAdd != ChromeBrowserProviderClient.INVALID_BOOKMARK_ID) {
startEditActivity(activity, new BookmarkId(idToAdd, BookmarkType.NORMAL));
return;
}

final BookmarkId enhancedId = bookmarkModel
.addBookmark(bookmarkModel.getDefaultFolder(), 0, tab.getTitle(), tab.getUrl());

Pair<EnhancedBookmarksModel, BookmarkId> pair = Pair.create(bookmarkModel, enhancedId);

SnackbarController snackbarController = new SnackbarController() {
@Override
public void onDismissForEachType(boolean isTimeout) {}

AddBookmarkCallback callback = new AddBookmarkCallback() {
@Override
public void onDismissNoAction(Object actionData) {
// This method will be called only if the snackbar is dismissed by timeout.
@SuppressWarnings("unchecked")
Pair<EnhancedBookmarksModel, BookmarkId> pair = (Pair<
EnhancedBookmarksModel, BookmarkId>) actionData;
pair.first.destroy();
}

@Override
public void onAction(Object actionData) {
@SuppressWarnings("unchecked")
Pair<EnhancedBookmarksModel, BookmarkId> pair = (Pair<
EnhancedBookmarksModel, BookmarkId>) actionData;
// Show edit activity with the name of parent folder highlighted.
startEditActivity(activity, enhancedId);
pair.first.destroy();
public void onBookmarkAdded(final BookmarkId enhancedId) {
Pair<EnhancedBookmarksModel, BookmarkId> pair =
Pair.create(bookmarkModel, enhancedId);

SnackbarController snackbarController = new SnackbarController() {
@Override
public void onDismissForEachType(boolean isTimeout) {}

@Override
public void onDismissNoAction(Object actionData) {
// This method will be called only if the snackbar is dismissed by timeout.
@SuppressWarnings("unchecked")
Pair<EnhancedBookmarksModel, BookmarkId> pair = (Pair<
EnhancedBookmarksModel, BookmarkId>) actionData;
pair.first.destroy();
}

@Override
public void onAction(Object actionData) {
@SuppressWarnings("unchecked")
Pair<EnhancedBookmarksModel, BookmarkId> pair = (Pair<
EnhancedBookmarksModel, BookmarkId>) actionData;
// Show edit activity with the name of parent folder highlighted.
startEditActivity(activity, enhancedId);
pair.first.destroy();
}
};

int messageId = bookmarkModel.getOfflinePageBridge() == null
? R.string.enhanced_bookmark_page_saved
: R.string.enhanced_bookmark_page_saved_offline_pages;
snackbarManager.showSnackbar(Snackbar.make(
activity.getString(messageId), snackbarController)
.setAction(activity.getString(R.string.enhanced_bookmark_item_edit), pair));
}
};
snackbarManager.showSnackbar(Snackbar.make(
activity.getString(R.string.enhanced_bookmark_page_saved), snackbarController)
.setAction(activity.getString(R.string.enhanced_bookmark_item_edit), pair));

bookmarkModel.addBookmarkAsync(bookmarkModel.getDefaultFolder(), 0, tab.getTitle(),
tab.getUrl(), tab.getWebContents(), callback);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.browser.BookmarksBridge;
import org.chromium.chrome.browser.offline_pages.OfflinePageBridge;
import org.chromium.chrome.browser.offline_pages.OfflinePageBridge.OfflinePageModelObserver;
import org.chromium.chrome.browser.offline_pages.OfflinePageBridge.SavePageCallback;
import org.chromium.chrome.browser.offline_pages.OfflinePageItem;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.components.bookmarks.BookmarkId;
import org.chromium.components.bookmarks.BookmarkType;
import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
import org.chromium.components.offline_pages.SavePageResult;
import org.chromium.content_public.browser.WebContents;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -25,6 +29,17 @@
public class EnhancedBookmarksModel extends BookmarksBridge {
private static final int FAVICON_MAX_CACHE_SIZE = 10 * 1024 * 1024; // 10MB

/**
* Callback for use with addBookmark.
*/
public interface AddBookmarkCallback {
/**
* Called when the bookmark has been added.
* @param bookmarkId ID of the bookmark that has been added.
*/
void onBookmarkAdded(BookmarkId bookmarkId);
}

/**
* Observer that listens to delete event. This interface is used by undo controllers to know
* which bookmarks were deleted. Note this observer only listens to events that go through
Expand All @@ -42,6 +57,8 @@ public interface EnhancedBookmarkDeleteObserver {

private ObserverList<EnhancedBookmarkDeleteObserver> mDeleteObservers = new ObserverList<>();
private OfflinePageBridge mOfflinePageBridge;
private boolean mIsOfflinePageModelLoaded;
private OfflinePageModelObserver mOfflinePageModelObserver;

/**
* Initialize enhanced bookmark model for last used non-incognito profile.
Expand All @@ -55,9 +72,41 @@ public EnhancedBookmarksModel(Profile profile) {
super(profile);

if (OfflinePageBridge.isEnabled()) {
// TODO(jianli): Make sure to wait until the bridge is loaded.
mOfflinePageBridge = new OfflinePageBridge(profile);
if (mOfflinePageBridge.isOfflinePageModelLoaded()) {
mIsOfflinePageModelLoaded = true;
} else {
mOfflinePageModelObserver = new OfflinePageModelObserver() {
@Override
public void offlinePageModelLoaded() {
mIsOfflinePageModelLoaded = true;
if (isBookmarkModelLoaded()) {
notifyBookmarkModelLoaded();
}
}
};
mOfflinePageBridge.addObserver(mOfflinePageModelObserver);
}
}
}

/**
* Clean up all the bridges. This must be called after done using this class.
*/
@Override
public void destroy() {
if (mOfflinePageBridge != null) {
mOfflinePageBridge.destroy();
mOfflinePageBridge = null;
}

super.destroy();
}

@Override
public boolean isBookmarkModelLoaded() {
return super.isBookmarkModelLoaded()
&& (mOfflinePageBridge == null || mIsOfflinePageModelLoaded);
}

/**
Expand Down Expand Up @@ -119,10 +168,37 @@ public void moveBookmarks(List<BookmarkId> bookmarkIds, BookmarkId newParentId)
}
}

@Override
public BookmarkId addBookmark(BookmarkId parent, int index, String title, String url) {
/**
* Add a new bookmark asynchronously.
*
* @param parent Folder where to add.
* @param index The position where the bookmark will be placed in parent folder
* @param title Title of the new bookmark.
* @param url Url of the new bookmark
* @param webContents A {@link WebContents} object.
* @param callback The callback to be invoked when the bookmark is added.
*/
public void addBookmarkAsync(BookmarkId parent, int index, String title, String url,
WebContents webContents, final AddBookmarkCallback callback) {
url = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url);
return super.addBookmark(parent, index, title, url);
final BookmarkId enhancedId = addBookmark(parent, index, title, url);

// If there is no need to save offline page, return now.
if (mOfflinePageBridge == null) {
callback.onBookmarkAdded(enhancedId);
return;
}

mOfflinePageBridge.savePage(webContents, enhancedId,
new SavePageCallback() {
@Override
public void onSavePageDone(int savePageResult, String url) {
// TODO(jianli): Error handling.
if (savePageResult == SavePageResult.SUCCESS) {
callback.onBookmarkAdded(enhancedId);
}
}
});
}

/**
Expand All @@ -132,6 +208,23 @@ public String getBookmarkTitle(BookmarkId bookmarkId) {
return getBookmarkById(bookmarkId).getTitle();
}

/**
* Returns the url used to launch a bookmark.
*
* @param bookmarkId ID of the bookmark to launch.
*/
public String getBookmarkLaunchUrl(BookmarkId bookmarkId) {
String url = getBookmarkById(bookmarkId).getUrl();
if (mOfflinePageBridge == null) {
return url;
}

// Return the offline url for the offline page.
OfflinePageItem page = mOfflinePageBridge.getPageByBookmarkId(bookmarkId);
return page == null ? url : page.getOfflineUrl();
}


/**
* @return The id of the default folder to add bookmarks/folders to.
*/
Expand All @@ -155,4 +248,11 @@ public List<BookmarkId> getBookmarkIDsByFilter(EnhancedBookmarkFilter filter) {
}
return bookmarkIds;
}

/**
* @return Offline page bridge.
*/
public OfflinePageBridge getOfflinePageBridge() {
return mOfflinePageBridge;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public final class OfflinePageBridge {
private static Boolean sIsEnabled;

/**
* Interface with callbacks to public calls on OfflinePageBrdige.
* Callback used to saving an offline page.
*/
public interface OfflinePageCallback {
public interface SavePageCallback {
/**
* Delivers result of saving a page.
*
Expand All @@ -42,17 +42,22 @@ public interface OfflinePageCallback {
* @param url URL of the saved page.
* @see OfflinePageBridge#savePage()
*/
@CalledByNative("OfflinePageCallback")
@CalledByNative("SavePageCallback")
void onSavePageDone(int savePageResult, String url);
}

/**
* Callback used to deleting an offline page.
*/
public interface DeletePageCallback {
/**
* Delivers result of deleting a page.
*
* @param deletePageResult Result of deleting the page. Uses
* {@see org.chromium.components.offline_pages.DeletePageResult} enum.
* @see OfflinePageBridge#deletePage()
*/
@CalledByNative("OfflinePageCallback")
@CalledByNative("DeletePageCallback")
void onDeletePageDone(int deletePageResult);
}

Expand Down Expand Up @@ -143,11 +148,11 @@ public OfflinePageItem getPageByBookmarkId(BookmarkId bookmarkId) {
* @param webContents Contents of the page to save.
* @param bookmarkId Id of the bookmark related to the offline page.
* @param callback Interface that contains a callback.
* @see OfflinePageCallback
* @see SavePageCallback
*/
@VisibleForTesting
public void savePage(
WebContents webContents, BookmarkId bookmarkId, OfflinePageCallback callback) {
WebContents webContents, BookmarkId bookmarkId, SavePageCallback callback) {
assert mIsNativeOfflinePageModelLoaded;
nativeSavePage(mNativeOfflinePageBridge, callback, webContents, bookmarkId.getId());
}
Expand All @@ -157,9 +162,10 @@ public void savePage(
*
* @param bookmarkId Bookmark ID for which the offline copy will be deleted.
* @param callback Interface that contains a callback.
* @see DeletePageCallback
*/
@VisibleForTesting
public void deletePage(BookmarkId bookmarkId, OfflinePageCallback callback) {
public void deletePage(BookmarkId bookmarkId, DeletePageCallback callback) {
assert mIsNativeOfflinePageModelLoaded;
nativeDeletePage(mNativeOfflinePageBridge, callback, bookmarkId.getId());
}
Expand Down Expand Up @@ -199,8 +205,8 @@ private native void nativeGetAllPages(
long nativeOfflinePageBridge, List<OfflinePageItem> offlinePages);
private native OfflinePageItem nativeGetPageByBookmarkId(
long nativeOfflinePageBridge, long bookmarkId);
private native void nativeSavePage(long nativeOfflinePageBridge, OfflinePageCallback callback,
private native void nativeSavePage(long nativeOfflinePageBridge, SavePageCallback callback,
WebContents webContents, long bookmarkId);
private native void nativeDeletePage(long nativeOfflinePageBridge,
OfflinePageCallback callback, long bookmarkId);
DeletePageCallback callback, long bookmarkId);
}
Loading

0 comments on commit ad61982

Please sign in to comment.