summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjianli <jianli@chromium.org>2015-09-23 17:59:31 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-24 01:00:00 +0000
commitcf6162c9d4b7eee6b58075079650467dbf6cebf7 (patch)
tree990c3f718cb79a75e3986b082975cb18a9997ff9
parentc00518520ed26072d2f3940145fe1dc9d45fa4c2 (diff)
downloadchromium_src-cf6162c9d4b7eee6b58075079650467dbf6cebf7.zip
chromium_src-cf6162c9d4b7eee6b58075079650467dbf6cebf7.tar.gz
chromium_src-cf6162c9d4b7eee6b58075079650467dbf6cebf7.tar.bz2
Update access info when an offline page is being visited
We need to update last access time and increase access count. BUG=491352 Patch Review URL: https://codereview.chromium.org/1345043002 Cr-Commit-Position: refs/heads/master@{#350425}
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java2
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java18
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java20
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageItem.java11
-rw-r--r--chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java31
-rw-r--r--chrome/browser/android/offline_pages/offline_page_bridge.cc12
-rw-r--r--chrome/browser/android/offline_pages/offline_page_bridge.h4
-rw-r--r--components/offline_pages/offline_page_item.cc9
-rw-r--r--components/offline_pages/offline_page_item.h2
-rw-r--r--components/offline_pages/offline_page_metadata_store.h6
-rw-r--r--components/offline_pages/offline_page_metadata_store_impl.cc6
-rw-r--r--components/offline_pages/offline_page_metadata_store_impl.h4
-rw-r--r--components/offline_pages/offline_page_metadata_store_impl_unittest.cc73
-rw-r--r--components/offline_pages/offline_page_model.cc26
-rw-r--r--components/offline_pages/offline_page_model.h8
-rw-r--r--components/offline_pages/offline_page_model_unittest.cc40
-rw-r--r--components/offline_pages/proto/offline_pages.proto3
17 files changed, 239 insertions, 36 deletions
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java
index c08c46e..f956945 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarkManager.java
@@ -414,7 +414,7 @@ public class EnhancedBookmarkManager implements EnhancedBookmarkDelegate {
public void openBookmark(BookmarkId bookmark, int launchLocation) {
clearSelection();
if (mEnhancedBookmarksModel.getBookmarkById(bookmark) != null) {
- String url = mEnhancedBookmarksModel.getBookmarkLaunchUrl(bookmark);
+ String url = mEnhancedBookmarksModel.getLaunchUrlAndMarkAccessed(bookmark);
// TODO(jianli): Notify the user about the failure.
if (TextUtils.isEmpty(url)) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java
index 3f25824..bbe2d6f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/enhancedbookmarks/EnhancedBookmarksModel.java
@@ -226,19 +226,25 @@ public class EnhancedBookmarksModel extends BookmarksBridge {
}
/**
- * Returns the url used to launch a bookmark.
+ * Retrieves the url to launch a bookmark or saved page. If latter, also marks it as being
+ * accessed.
*
* @param bookmarkId ID of the bookmark to launch.
+ * @return The launch URL.
*/
- public String getBookmarkLaunchUrl(BookmarkId bookmarkId) {
+ public String getLaunchUrlAndMarkAccessed(BookmarkId bookmarkId) {
String url = getBookmarkById(bookmarkId).getUrl();
- if (mOfflinePageBridge == null) {
- return url;
- }
+ if (mOfflinePageBridge == null) return url;
// Return the offline url for the offline page.
OfflinePageItem page = mOfflinePageBridge.getPageByBookmarkId(bookmarkId);
- return page == null ? url : page.getOfflineUrl();
+ if (page == null) return url;
+
+ // Mark that the offline page has been accessed, that will cause last access time and access
+ // count being updated.
+ mOfflinePageBridge.markPageAccessed(bookmarkId);
+
+ return page.getOfflineUrl();
}
/**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java
index 1c698fce..c60229a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java
@@ -161,6 +161,16 @@ public final class OfflinePageBridge {
}
/**
+ * Marks that an offline page related to a specified bookmark has been accessed.
+ *
+ * @param bookmarkId Bookmark ID for which the offline copy will be deleted.
+ */
+ public void markPageAccessed(BookmarkId bookmarkId) {
+ assert mIsNativeOfflinePageModelLoaded;
+ nativeMarkPageAccessed(mNativeOfflinePageBridge, bookmarkId.getId());
+ }
+
+ /**
* Deletes an offline page related to a specified bookmark.
*
* @param bookmarkId Bookmark ID for which the offline copy will be deleted.
@@ -217,14 +227,15 @@ public final class OfflinePageBridge {
@CalledByNative
private static void createOfflinePageAndAddToList(List<OfflinePageItem> offlinePagesList,
- String url, long bookmarkId, String offlineUrl, long fileSize) {
- offlinePagesList.add(createOfflinePageItem(url, bookmarkId, offlineUrl, fileSize));
+ String url, long bookmarkId, String offlineUrl, long fileSize, int accessCount) {
+ offlinePagesList.add(createOfflinePageItem(url, bookmarkId, offlineUrl, fileSize,
+ accessCount));
}
@CalledByNative
private static OfflinePageItem createOfflinePageItem(
- String url, long bookmarkId, String offlineUrl, long fileSize) {
- return new OfflinePageItem(url, bookmarkId, offlineUrl, fileSize);
+ String url, long bookmarkId, String offlineUrl, long fileSize, int accessCount) {
+ return new OfflinePageItem(url, bookmarkId, offlineUrl, fileSize, accessCount);
}
private static native boolean nativeIsOfflinePagesEnabled();
@@ -237,6 +248,7 @@ public final class OfflinePageBridge {
long nativeOfflinePageBridge, long bookmarkId);
private native void nativeSavePage(long nativeOfflinePageBridge, SavePageCallback callback,
WebContents webContents, long bookmarkId);
+ private native void nativeMarkPageAccessed(long nativeOfflinePageBridge, long bookmarkId);
private native void nativeDeletePage(long nativeOfflinePageBridge,
DeletePageCallback callback, long bookmarkId);
private native void nativeDeletePages(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageItem.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageItem.java
index 8efc1b7..a73b125 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageItem.java
@@ -16,12 +16,15 @@ public class OfflinePageItem {
private final BookmarkId mBookmarId;
private final String mOfflineUrl;
private final long mFileSize;
+ private final int mAccessCount;
- public OfflinePageItem(String url, long bookmarkId, String offlineUrl, long fileSize) {
+ public OfflinePageItem(String url, long bookmarkId, String offlineUrl, long fileSize,
+ int accessCount) {
mUrl = url;
mBookmarId = new BookmarkId(bookmarkId, BookmarkType.NORMAL);
mOfflineUrl = offlineUrl;
mFileSize = fileSize;
+ mAccessCount = accessCount;
}
/** @return URL of the offline page. */
@@ -47,4 +50,10 @@ public class OfflinePageItem {
public long getFileSize() {
return mFileSize;
}
+
+ /** @return Number of times that the offline archive has been accessed. */
+ @VisibleForTesting
+ public int getAccessCount() {
+ return mAccessCount;
+ }
}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
index 67fe59f..522ec42 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
@@ -18,6 +18,8 @@ import org.chromium.components.bookmarks.BookmarkId;
import org.chromium.components.bookmarks.BookmarkType;
import org.chromium.components.offlinepages.DeletePageResult;
import org.chromium.components.offlinepages.SavePageResult;
+import org.chromium.content.browser.test.util.Criteria;
+import org.chromium.content.browser.test.util.CriteriaHelper;
import java.util.ArrayList;
import java.util.List;
@@ -92,6 +94,17 @@ public class OfflinePageBridgeTest extends ChromeActivityTestCaseBase<ChromeActi
}
@MediumTest
+ public void testMarkPageAccessed() throws Exception {
+ loadUrl(TEST_PAGE);
+ savePage(SavePageResult.SUCCESS, TEST_PAGE);
+ OfflinePageItem offlinePage = mOfflinePageBridge.getPageByBookmarkId(BOOKMARK_ID);
+ assertNotNull("Offline page should be available, but it is not.", offlinePage);
+ assertEquals("Offline page access count should be 0.", 0, offlinePage.getAccessCount());
+
+ markPageAccessed(BOOKMARK_ID, 1);
+ }
+
+ @MediumTest
public void testGetPageByBookmarkId() throws Exception {
loadUrl(TEST_PAGE);
savePage(SavePageResult.SUCCESS, TEST_PAGE);
@@ -148,6 +161,24 @@ public class OfflinePageBridgeTest extends ChromeActivityTestCaseBase<ChromeActi
assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
+ private void markPageAccessed(final BookmarkId bookmarkId, final int expectedAccessCount)
+ throws InterruptedException {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ mOfflinePageBridge.markPageAccessed(bookmarkId);
+ }
+ });
+ assertTrue(CriteriaHelper.pollForUIThreadCriteria(new Criteria() {
+ @Override
+ public boolean isSatisfied() {
+ OfflinePageItem offlinePage =
+ mOfflinePageBridge.getPageByBookmarkId(bookmarkId);
+ return offlinePage.getAccessCount() == expectedAccessCount;
+ }
+ }));
+ }
+
private void deletePage(BookmarkId bookmarkId, final int expectedResult)
throws InterruptedException {
final Semaphore semaphore = new Semaphore(0);
diff --git a/chrome/browser/android/offline_pages/offline_page_bridge.cc b/chrome/browser/android/offline_pages/offline_page_bridge.cc
index af4ba46..5a03f9c9 100644
--- a/chrome/browser/android/offline_pages/offline_page_bridge.cc
+++ b/chrome/browser/android/offline_pages/offline_page_bridge.cc
@@ -61,7 +61,8 @@ void ToJavaOfflinePageList(JNIEnv* env,
ConvertUTF8ToJavaString(env, offline_page.url.spec()).obj(),
offline_page.bookmark_id,
ConvertUTF8ToJavaString(env, offline_page.GetOfflineURL().spec()).obj(),
- offline_page.file_size);
+ offline_page.file_size,
+ offline_page.access_count);
}
}
@@ -126,7 +127,8 @@ ScopedJavaLocalRef<jobject> OfflinePageBridge::GetPageByBookmarkId(
env, ConvertUTF8ToJavaString(env, offline_page->url.spec()).obj(),
offline_page->bookmark_id,
ConvertUTF8ToJavaString(env, offline_page->GetOfflineURL().spec()).obj(),
- offline_page->file_size);
+ offline_page->file_size,
+ offline_page->access_count);
}
void OfflinePageBridge::SavePage(JNIEnv* env,
@@ -153,6 +155,12 @@ void OfflinePageBridge::SavePage(JNIEnv* env,
base::Bind(&SavePageCallback, j_callback_ref, url));
}
+void OfflinePageBridge::MarkPageAccessed(JNIEnv* env,
+ jobject obj,
+ jlong bookmark_id) {
+ offline_page_model_->MarkPageAccessed(bookmark_id);
+}
+
void OfflinePageBridge::DeletePage(JNIEnv* env,
jobject obj,
jobject j_callback_obj,
diff --git a/chrome/browser/android/offline_pages/offline_page_bridge.h b/chrome/browser/android/offline_pages/offline_page_bridge.h
index a0b3007..b19ff97 100644
--- a/chrome/browser/android/offline_pages/offline_page_bridge.h
+++ b/chrome/browser/android/offline_pages/offline_page_bridge.h
@@ -51,6 +51,10 @@ class OfflinePageBridge : public OfflinePageModel::Observer {
jobject j_web_contents,
jlong bookmark_id);
+ void MarkPageAccessed(JNIEnv* env,
+ jobject obj,
+ jlong bookmark_id);
+
void DeletePage(JNIEnv* env,
jobject obj,
jobject j_callback_obj,
diff --git a/components/offline_pages/offline_page_item.cc b/components/offline_pages/offline_page_item.cc
index 4e4d697..a017f7b 100644
--- a/components/offline_pages/offline_page_item.cc
+++ b/components/offline_pages/offline_page_item.cc
@@ -14,7 +14,8 @@ const int kCurrentVersion = 1;
OfflinePageItem::OfflinePageItem()
: version(kCurrentVersion),
- file_size(0) {
+ file_size(0),
+ access_count(0) {
}
OfflinePageItem::OfflinePageItem(const GURL& url,
@@ -25,7 +26,8 @@ OfflinePageItem::OfflinePageItem(const GURL& url,
bookmark_id(bookmark_id),
version(kCurrentVersion),
file_path(file_path),
- file_size(file_size) {
+ file_size(file_size),
+ access_count(0) {
}
OfflinePageItem::OfflinePageItem(const GURL& url,
@@ -39,7 +41,8 @@ OfflinePageItem::OfflinePageItem(const GURL& url,
file_path(file_path),
file_size(file_size),
creation_time(creation_time),
- last_access_time(creation_time) {
+ last_access_time(creation_time),
+ access_count(0) {
}
OfflinePageItem::~OfflinePageItem() {
diff --git a/components/offline_pages/offline_page_item.h b/components/offline_pages/offline_page_item.h
index ac9bcb8..0ae4a8c 100644
--- a/components/offline_pages/offline_page_item.h
+++ b/components/offline_pages/offline_page_item.h
@@ -47,6 +47,8 @@ struct OfflinePageItem {
base::Time creation_time;
// The time when the offline archive was last accessed.
base::Time last_access_time;
+ // Number of times that the offline archive has been accessed.
+ int access_count;
};
} // namespace offline_pages
diff --git a/components/offline_pages/offline_page_metadata_store.h b/components/offline_pages/offline_page_metadata_store.h
index 18620bd..d50159f 100644
--- a/components/offline_pages/offline_page_metadata_store.h
+++ b/components/offline_pages/offline_page_metadata_store.h
@@ -32,10 +32,10 @@ class OfflinePageMetadataStore {
// Get all of the offline pages from the store.
virtual void Load(const LoadCallback& callback) = 0;
- // Asynchronously adds offline page metadata to the store.
+ // Asynchronously adds or updates offline page metadata to the store.
// Result of the update is passed in callback.
- virtual void AddOfflinePage(const OfflinePageItem& offline_page,
- const UpdateCallback& callback) = 0;
+ virtual void AddOrUpdateOfflinePage(const OfflinePageItem& offline_page,
+ const UpdateCallback& callback) = 0;
// Asynchronously removes offline page metadata from the store.
// Result of the update is passed in callback.
diff --git a/components/offline_pages/offline_page_metadata_store_impl.cc b/components/offline_pages/offline_page_metadata_store_impl.cc
index 90b7b45..b9801f7 100644
--- a/components/offline_pages/offline_page_metadata_store_impl.cc
+++ b/components/offline_pages/offline_page_metadata_store_impl.cc
@@ -43,6 +43,7 @@ void OfflinePageItemToEntry(const OfflinePageItem& item,
item_proto->set_file_size(item.file_size);
item_proto->set_creation_time(item.creation_time.ToInternalValue());
item_proto->set_last_access_time(item.last_access_time.ToInternalValue());
+ item_proto->set_access_count(item.access_count);
}
bool OfflinePageItemFromEntry(const offline_pages::OfflinePageEntry& item_proto,
@@ -71,6 +72,9 @@ bool OfflinePageItemFromEntry(const offline_pages::OfflinePageEntry& item_proto,
item->last_access_time =
base::Time::FromInternalValue(item_proto.last_access_time());
}
+ if (item_proto.has_access_count()) {
+ item->access_count = item_proto.access_count();
+ }
return true;
}
@@ -155,7 +159,7 @@ void OfflinePageMetadataStoreImpl::Load(const LoadCallback& callback) {
weak_ptr_factory_.GetWeakPtr())));
}
-void OfflinePageMetadataStoreImpl::AddOfflinePage(
+void OfflinePageMetadataStoreImpl::AddOrUpdateOfflinePage(
const OfflinePageItem& offline_page_item,
const UpdateCallback& callback) {
scoped_ptr<ProtoDatabase<OfflinePageEntry>::KeyEntryVector> entries_to_save(
diff --git a/components/offline_pages/offline_page_metadata_store_impl.h b/components/offline_pages/offline_page_metadata_store_impl.h
index 828f935..3bab989 100644
--- a/components/offline_pages/offline_page_metadata_store_impl.h
+++ b/components/offline_pages/offline_page_metadata_store_impl.h
@@ -35,8 +35,8 @@ class OfflinePageMetadataStoreImpl : public OfflinePageMetadataStore {
// OfflinePageMetadataStore implementation:
void Load(const LoadCallback& callback) override;
- void AddOfflinePage(const OfflinePageItem& offline_page_record,
- const UpdateCallback& callback) override;
+ void AddOrUpdateOfflinePage(const OfflinePageItem& offline_page_record,
+ const UpdateCallback& callback) override;
void RemoveOfflinePages(const std::vector<int64>& bookmark_ids,
const UpdateCallback& callback) override;
diff --git a/components/offline_pages/offline_page_metadata_store_impl_unittest.cc b/components/offline_pages/offline_page_metadata_store_impl_unittest.cc
index 30ce39c..8ea31cf 100644
--- a/components/offline_pages/offline_page_metadata_store_impl_unittest.cc
+++ b/components/offline_pages/offline_page_metadata_store_impl_unittest.cc
@@ -122,7 +122,7 @@ TEST_F(OfflinePageMetadataStoreImplTest, AddOfflinePageThenLoad) {
OfflinePageItem offline_page(GURL(kTestURL), kTestBookmarkId,
base::FilePath(kFilePath), kFileSize);
- store->AddOfflinePage(
+ store->AddOrUpdateOfflinePage(
offline_page,
base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback,
base::Unretained(this), ADD));
@@ -154,7 +154,7 @@ TEST_F(OfflinePageMetadataStoreImplTest, AddOfflinePageRestartLoad) {
OfflinePageItem offline_page(GURL(kTestURL), kTestBookmarkId,
base::FilePath(kFilePath), kFileSize);
- store->AddOfflinePage(
+ store->AddOrUpdateOfflinePage(
offline_page,
base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback,
base::Unretained(this), ADD));
@@ -180,6 +180,7 @@ TEST_F(OfflinePageMetadataStoreImplTest, AddOfflinePageRestartLoad) {
EXPECT_EQ(offline_page.file_size, offline_pages_[0].file_size);
EXPECT_EQ(offline_page.creation_time, offline_pages_[0].creation_time);
EXPECT_EQ(offline_page.last_access_time, offline_pages_[0].last_access_time);
+ EXPECT_EQ(offline_page.access_count, offline_pages_[0].access_count);
}
// Tests removing offline page metadata from the store, for which it first adds
@@ -189,7 +190,7 @@ TEST_F(OfflinePageMetadataStoreImplTest, RemoveOfflinePage) {
OfflinePageItem offline_page(GURL(kTestURL), kTestBookmarkId,
base::FilePath(kFilePath), kFileSize);
- store->AddOfflinePage(
+ store->AddOrUpdateOfflinePage(
offline_page,
base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback,
base::Unretained(this), ADD));
@@ -252,7 +253,7 @@ TEST_F(OfflinePageMetadataStoreImplTest, AddRemoveMultipleOfflinePages) {
base::FilePath(FILE_PATH_LITERAL("//other.page.com.mhtml"));
OfflinePageItem offline_page_2(GURL("https://other.page.com"), 5678LL,
file_path_2, 12345, base::Time::Now());
- store->AddOfflinePage(
+ store->AddOrUpdateOfflinePage(
offline_page_1,
base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback,
base::Unretained(this), ADD));
@@ -261,7 +262,7 @@ TEST_F(OfflinePageMetadataStoreImplTest, AddRemoveMultipleOfflinePages) {
EXPECT_EQ(STATUS_TRUE, last_status_);
ClearResults();
- store->AddOfflinePage(
+ store->AddOrUpdateOfflinePage(
offline_page_2,
base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback,
base::Unretained(this), ADD));
@@ -306,6 +307,68 @@ TEST_F(OfflinePageMetadataStoreImplTest, AddRemoveMultipleOfflinePages) {
EXPECT_EQ(offline_page_2.creation_time, offline_pages_[0].creation_time);
EXPECT_EQ(offline_page_2.last_access_time,
offline_pages_[0].last_access_time);
+ EXPECT_EQ(offline_page_2.access_count, offline_pages_[0].access_count);
+}
+
+// Tests updating offline page metadata from the store.
+TEST_F(OfflinePageMetadataStoreImplTest, UpdateOfflinePage) {
+ scoped_ptr<OfflinePageMetadataStoreImpl> store(BuildStore());
+
+ // First, adds a fresh page.
+ OfflinePageItem offline_page(GURL(kTestURL), kTestBookmarkId,
+ base::FilePath(kFilePath), kFileSize);
+ store->AddOrUpdateOfflinePage(
+ offline_page,
+ base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback,
+ base::Unretained(this), ADD));
+ PumpLoop();
+ EXPECT_EQ(ADD, last_called_callback_);
+ EXPECT_EQ(STATUS_TRUE, last_status_);
+
+ ClearResults();
+ store->Load(base::Bind(&OfflinePageMetadataStoreImplTest::LoadCallback,
+ base::Unretained(this)));
+ PumpLoop();
+
+ EXPECT_EQ(LOAD, last_called_callback_);
+ EXPECT_EQ(STATUS_TRUE, last_status_);
+ EXPECT_EQ(1U, offline_pages_.size());
+ EXPECT_EQ(offline_page.url, offline_pages_[0].url);
+ EXPECT_EQ(offline_page.bookmark_id, offline_pages_[0].bookmark_id);
+ EXPECT_EQ(offline_page.version, offline_pages_[0].version);
+ EXPECT_EQ(offline_page.file_path, offline_pages_[0].file_path);
+ EXPECT_EQ(offline_page.file_size, offline_pages_[0].file_size);
+ EXPECT_EQ(offline_page.creation_time, offline_pages_[0].creation_time);
+ EXPECT_EQ(offline_page.last_access_time, offline_pages_[0].last_access_time);
+ EXPECT_EQ(offline_page.access_count, offline_pages_[0].access_count);
+
+ // Then updates some data.
+ offline_page.file_size = kFileSize + 1;
+ offline_page.access_count++;
+ store->AddOrUpdateOfflinePage(
+ offline_page,
+ base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback,
+ base::Unretained(this), ADD));
+ PumpLoop();
+ EXPECT_EQ(ADD, last_called_callback_);
+ EXPECT_EQ(STATUS_TRUE, last_status_);
+
+ ClearResults();
+ store->Load(base::Bind(&OfflinePageMetadataStoreImplTest::LoadCallback,
+ base::Unretained(this)));
+ PumpLoop();
+
+ EXPECT_EQ(LOAD, last_called_callback_);
+ EXPECT_EQ(STATUS_TRUE, last_status_);
+ EXPECT_EQ(1U, offline_pages_.size());
+ EXPECT_EQ(offline_page.url, offline_pages_[0].url);
+ EXPECT_EQ(offline_page.bookmark_id, offline_pages_[0].bookmark_id);
+ EXPECT_EQ(offline_page.version, offline_pages_[0].version);
+ EXPECT_EQ(offline_page.file_path, offline_pages_[0].file_path);
+ EXPECT_EQ(offline_page.file_size, offline_pages_[0].file_size);
+ EXPECT_EQ(offline_page.creation_time, offline_pages_[0].creation_time);
+ EXPECT_EQ(offline_page.last_access_time, offline_pages_[0].last_access_time);
+ EXPECT_EQ(offline_page.access_count, offline_pages_[0].access_count);
}
} // namespace
diff --git a/components/offline_pages/offline_page_model.cc b/components/offline_pages/offline_page_model.cc
index f4d7870..a3eac94 100644
--- a/components/offline_pages/offline_page_model.cc
+++ b/components/offline_pages/offline_page_model.cc
@@ -112,6 +112,23 @@ void OfflinePageModel::SavePage(const GURL& url,
pending_archivers_.push_back(archiver.Pass());
}
+void OfflinePageModel::MarkPageAccessed(int64 bookmark_id) {
+ DCHECK(is_loaded_);
+ auto iter = offline_pages_.find(bookmark_id);
+ if (iter == offline_pages_.end())
+ return;
+
+ // Make a copy of the cached item and update it. The cached item should only
+ // be updated upon the successful store operation.
+ OfflinePageItem offline_page_item = iter->second;
+ offline_page_item.last_access_time = base::Time::Now();
+ offline_page_item.access_count++;
+ store_->AddOrUpdateOfflinePage(
+ offline_page_item,
+ base::Bind(&OfflinePageModel::OnUpdateOfflinePageDone,
+ weak_ptr_factory_.GetWeakPtr(), offline_page_item));
+}
+
void OfflinePageModel::DeletePageByBookmarkId(
int64 bookmark_id,
const DeletePageCallback& callback) {
@@ -216,7 +233,7 @@ void OfflinePageModel::OnCreateArchiveDone(const GURL& requested_url,
OfflinePageItem offline_page_item(url, bookmark_id, file_path, file_size,
base::Time::Now());
- store_->AddOfflinePage(
+ store_->AddOrUpdateOfflinePage(
offline_page_item,
base::Bind(&OfflinePageModel::OnAddOfflinePageDone,
weak_ptr_factory_.GetWeakPtr(), archiver, callback,
@@ -240,6 +257,13 @@ void OfflinePageModel::OnAddOfflinePageDone(OfflinePageArchiver* archiver,
DeletePendingArchiver(archiver);
}
+void OfflinePageModel::OnUpdateOfflinePageDone(
+ const OfflinePageItem& offline_page_item, bool success) {
+ // Update the item in the cache only upon success.
+ if (success)
+ offline_pages_[offline_page_item.bookmark_id] = offline_page_item;
+}
+
void OfflinePageModel::BookmarkModelChanged() {
}
diff --git a/components/offline_pages/offline_page_model.h b/components/offline_pages/offline_page_model.h
index dd55a7e..648a0f4 100644
--- a/components/offline_pages/offline_page_model.h
+++ b/components/offline_pages/offline_page_model.h
@@ -130,6 +130,11 @@ class OfflinePageModel : public KeyedService,
scoped_ptr<OfflinePageArchiver> archiver,
const SavePageCallback& callback);
+ // Marks that the offline page related to the passed |bookmark_id| has been
+ // accessed. Its access info, including last access time and access count,
+ // will be updated. Requires that the model is loaded.
+ void MarkPageAccessed(int64 bookmark_id);
+
// Deletes an offline page related to the passed |bookmark_id|. Requires that
// the model is loaded.
void DeletePageByBookmarkId(int64 bookmark_id,
@@ -203,6 +208,9 @@ class OfflinePageModel : public KeyedService,
void InformDeletePageDone(const DeletePageCallback& callback,
DeletePageResult result);
+ void OnUpdateOfflinePageDone(const OfflinePageItem& offline_page_item,
+ bool success);
+
// Persistent store for offline page metadata.
scoped_ptr<OfflinePageMetadataStore> store_;
diff --git a/components/offline_pages/offline_page_model_unittest.cc b/components/offline_pages/offline_page_model_unittest.cc
index f60e0f5..0aa80ab 100644
--- a/components/offline_pages/offline_page_model_unittest.cc
+++ b/components/offline_pages/offline_page_model_unittest.cc
@@ -48,8 +48,8 @@ class OfflinePageTestStore : public OfflinePageMetadataStore {
// OfflinePageMetadataStore overrides:
void Load(const LoadCallback& callback) override;
- void AddOfflinePage(const OfflinePageItem& offline_page,
- const UpdateCallback& callback) override;
+ void AddOrUpdateOfflinePage(const OfflinePageItem& offline_page,
+ const UpdateCallback& callback) override;
void RemoveOfflinePages(const std::vector<int64>& bookmark_ids,
const UpdateCallback& callback) override;
const OfflinePageItem& last_saved_page() const { return last_saved_page_; }
@@ -95,8 +95,8 @@ void OfflinePageTestStore::Load(const LoadCallback& callback) {
}
}
-void OfflinePageTestStore::AddOfflinePage(const OfflinePageItem& offline_page,
- const UpdateCallback& callback) {
+void OfflinePageTestStore::AddOrUpdateOfflinePage(
+ const OfflinePageItem& offline_page, const UpdateCallback& callback) {
last_saved_page_ = offline_page;
bool result = scenario_ != TestScenario::WRITE_FAILED;
if (result) {
@@ -370,6 +370,7 @@ TEST_F(OfflinePageModelTest, SavePageSuccessful) {
EXPECT_EQ(kTestPageBookmarkId1, offline_pages[0].bookmark_id);
EXPECT_EQ(archiver_path, offline_pages[0].file_path);
EXPECT_EQ(kTestFileSize, offline_pages[0].file_size);
+ EXPECT_EQ(0, offline_pages[0].access_count);
}
TEST_F(OfflinePageModelTest, SavePageOfflineArchiverCancelled) {
@@ -503,10 +504,35 @@ TEST_F(OfflinePageModelTest, SavePageOfflineArchiverTwoPages) {
EXPECT_EQ(kTestPageBookmarkId1, offline_pages[0].bookmark_id);
EXPECT_EQ(archiver_path, offline_pages[0].file_path);
EXPECT_EQ(kTestFileSize, offline_pages[0].file_size);
+ EXPECT_EQ(0, offline_pages[0].access_count);
EXPECT_EQ(kTestUrl2, offline_pages[1].url);
EXPECT_EQ(kTestPageBookmarkId2, offline_pages[1].bookmark_id);
EXPECT_EQ(archiver_path2, offline_pages[1].file_path);
EXPECT_EQ(kTestFileSize, offline_pages[1].file_size);
+ EXPECT_EQ(0, offline_pages[1].access_count);
+}
+
+TEST_F(OfflinePageModelTest, MarkPageAccessed) {
+ scoped_ptr<OfflinePageTestArchiver> archiver(
+ BuildArchiver(kTestUrl,
+ OfflinePageArchiver::ArchiverResult::SUCCESSFULLY_CREATED)
+ .Pass());
+ model()->SavePage(
+ kTestUrl, kTestPageBookmarkId1, archiver.Pass(),
+ base::Bind(&OfflinePageModelTest::OnSavePageDone, AsWeakPtr()));
+ PumpLoop();
+
+ // This will increase access_count by one.
+ model()->MarkPageAccessed(kTestPageBookmarkId1);
+ base::RunLoop().RunUntilIdle();
+
+ const std::vector<OfflinePageItem>& offline_pages = model()->GetAllPages();
+
+ EXPECT_EQ(1UL, offline_pages.size());
+ EXPECT_EQ(kTestUrl, offline_pages[0].url);
+ EXPECT_EQ(kTestPageBookmarkId1, offline_pages[0].bookmark_id);
+ EXPECT_EQ(kTestFileSize, offline_pages[0].file_size);
+ EXPECT_EQ(1, offline_pages[0].access_count);
}
TEST_F(OfflinePageModelTest, GetAllPagesStoreEmpty) {
@@ -692,7 +718,7 @@ TEST_F(OfflinePageModelTest, GetPagesToCleanUp) {
GURL(kTestUrl), kTestPageBookmarkId1,
base::FilePath(FILE_PATH_LITERAL("/test/location/page1.mhtml")),
kTestFileSize, now - base::TimeDelta::FromDays(40));
- GetStore()->AddOfflinePage(
+ GetStore()->AddOrUpdateOfflinePage(
page_1,
base::Bind(&OfflinePageModelTest::OnStoreUpdateDone, AsWeakPtr()));
PumpLoop();
@@ -701,7 +727,7 @@ TEST_F(OfflinePageModelTest, GetPagesToCleanUp) {
GURL(kTestUrl2), kTestPageBookmarkId2,
base::FilePath(FILE_PATH_LITERAL("/test/location/page2.mhtml")),
kTestFileSize, now - base::TimeDelta::FromDays(31));
- GetStore()->AddOfflinePage(
+ GetStore()->AddOrUpdateOfflinePage(
page_2,
base::Bind(&OfflinePageModelTest::OnStoreUpdateDone, AsWeakPtr()));
PumpLoop();
@@ -710,7 +736,7 @@ TEST_F(OfflinePageModelTest, GetPagesToCleanUp) {
GURL("http://test.xyz"), 42,
base::FilePath(FILE_PATH_LITERAL("/test/location/page3.mhtml")),
kTestFileSize, now - base::TimeDelta::FromDays(29));
- GetStore()->AddOfflinePage(
+ GetStore()->AddOrUpdateOfflinePage(
page_3,
base::Bind(&OfflinePageModelTest::OnStoreUpdateDone, AsWeakPtr()));
PumpLoop();
diff --git a/components/offline_pages/proto/offline_pages.proto b/components/offline_pages/proto/offline_pages.proto
index 07025a1..16d8b8f 100644
--- a/components/offline_pages/proto/offline_pages.proto
+++ b/components/offline_pages/proto/offline_pages.proto
@@ -33,4 +33,7 @@ message OfflinePageEntry {
// Last access time of the offline archive.
optional int64 last_access_time = 7;
+
+ // Number of times that the offline archive has been accessed.
+ optional int32 access_count = 8;
}