summaryrefslogtreecommitdiffstats
path: root/ios
diff options
context:
space:
mode:
authorolivierrobin <olivierrobin@chromium.org>2016-03-24 09:17:18 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-24 16:18:36 +0000
commit883e7c4f4fe29b50cc43d15b9f0d8ef0f3a65e1f (patch)
tree983e2e7f8273d36fc7c6e0a71abc8dc9ab3535cf /ios
parent9741145b1c98047f11ed1b795166ea97ec0829a1 (diff)
downloadchromium_src-883e7c4f4fe29b50cc43d15b9f0d8ef0f3a65e1f.zip
chromium_src-883e7c4f4fe29b50cc43d15b9f0d8ef0f3a65e1f.tar.gz
chromium_src-883e7c4f4fe29b50cc43d15b9f0d8ef0f3a65e1f.tar.bz2
Add persistence layer to Reading list model
Review URL: https://codereview.chromium.org/1815633003 Cr-Commit-Position: refs/heads/master@{#383073}
Diffstat (limited to 'ios')
-rw-r--r--ios/chrome/browser/reading_list/reading_list_model.h2
-rw-r--r--ios/chrome/browser/reading_list/reading_list_model_factory.cc5
-rw-r--r--ios/chrome/browser/reading_list/reading_list_model_memory.cc42
-rw-r--r--ios/chrome/browser/reading_list/reading_list_model_memory.h15
-rw-r--r--ios/chrome/browser/reading_list/reading_list_model_storage.h27
-rw-r--r--ios/chrome/browser/reading_list/reading_list_model_storage_defaults.h28
-rw-r--r--ios/chrome/browser/reading_list/reading_list_model_storage_defaults.mm103
-rw-r--r--ios/chrome/ios_chrome.gyp3
8 files changed, 222 insertions, 3 deletions
diff --git a/ios/chrome/browser/reading_list/reading_list_model.h b/ios/chrome/browser/reading_list/reading_list_model.h
index d731909..8c4c98f 100644
--- a/ios/chrome/browser/reading_list/reading_list_model.h
+++ b/ios/chrome/browser/reading_list/reading_list_model.h
@@ -99,7 +99,7 @@ class ReadingListModel {
// Tells model that batch updates have completed. Called from
// ReadingListBatchUpdateToken dtor.
- void EndBatchUpdates();
+ virtual void EndBatchUpdates();
private:
unsigned int current_batch_updates_count_;
diff --git a/ios/chrome/browser/reading_list/reading_list_model_factory.cc b/ios/chrome/browser/reading_list/reading_list_model_factory.cc
index dcf6c2b..1705249 100644
--- a/ios/chrome/browser/reading_list/reading_list_model_factory.cc
+++ b/ios/chrome/browser/reading_list/reading_list_model_factory.cc
@@ -11,6 +11,7 @@
#include "ios/chrome/browser/browser_state/browser_state_otr_helper.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#include "ios/chrome/browser/reading_list/reading_list_model_memory.h"
+#include "ios/chrome/browser/reading_list/reading_list_model_storage_defaults.h"
// static
ReadingListModel* ReadingListModelFactory::GetForBrowserState(
@@ -40,8 +41,10 @@ ReadingListModelFactory::~ReadingListModelFactory() {}
scoped_ptr<KeyedService> ReadingListModelFactory::BuildServiceInstanceFor(
web::BrowserState* context) const {
+ std::unique_ptr<ReadingListModelStorage> storage(
+ new ReadingListModelStorageDefaults());
scoped_ptr<ReadingListModelMemory> reading_list_model(
- new ReadingListModelMemory());
+ new ReadingListModelMemory(std::move(storage)));
return std::move(reading_list_model);
}
diff --git a/ios/chrome/browser/reading_list/reading_list_model_memory.cc b/ios/chrome/browser/reading_list/reading_list_model_memory.cc
index d5ff979..7d9f99a 100644
--- a/ios/chrome/browser/reading_list/reading_list_model_memory.cc
+++ b/ios/chrome/browser/reading_list/reading_list_model_memory.cc
@@ -3,11 +3,24 @@
// found in the LICENSE file.
#include "ios/chrome/browser/reading_list/reading_list_model_memory.h"
+#include "ios/chrome/browser/reading_list/reading_list_model_storage.h"
#include "url/gurl.h"
ReadingListModelMemory::ReadingListModelMemory()
- : hasUnseen_(false), loaded_(true) {}
+ : ReadingListModelMemory(NULL) {}
+
+ReadingListModelMemory::ReadingListModelMemory(
+ std::unique_ptr<ReadingListModelStorage> storage)
+ : hasUnseen_(false) {
+ if (storage) {
+ storageLayer_ = std::move(storage);
+ read_ = storageLayer_->LoadPersistentReadList();
+ unread_ = storageLayer_->LoadPersistentUnreadList();
+ hasUnseen_ = storageLayer_->LoadPersistentHasUnseen();
+ }
+ loaded_ = true;
+}
ReadingListModelMemory::~ReadingListModelMemory() {}
void ReadingListModelMemory::Shutdown() {
@@ -38,6 +51,9 @@ bool ReadingListModelMemory::HasUnseenEntries() const {
void ReadingListModelMemory::ResetUnseenEntries() {
DCHECK(loaded());
hasUnseen_ = false;
+ if (storageLayer_ && !IsPerformingBatchUpdates()) {
+ storageLayer_->SavePersistentHasUnseen(false);
+ }
}
// Returns a specific entry.
@@ -62,6 +78,9 @@ void ReadingListModelMemory::RemoveEntryByUrl(const GURL& url) {
ReadingListWillRemoveUnreadEntry(
this, std::distance(unread_.begin(), result)));
unread_.erase(result);
+ if (storageLayer_ && !IsPerformingBatchUpdates()) {
+ storageLayer_->SavePersistentUnreadList(unread_);
+ }
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
ReadingListDidApplyChanges(this));
return;
@@ -73,6 +92,9 @@ void ReadingListModelMemory::RemoveEntryByUrl(const GURL& url) {
ReadingListWillRemoveReadEntry(
this, std::distance(read_.begin(), result)));
read_.erase(result);
+ if (storageLayer_ && !IsPerformingBatchUpdates()) {
+ storageLayer_->SavePersistentReadList(read_);
+ }
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
ReadingListDidApplyChanges(this));
return;
@@ -89,6 +111,10 @@ const ReadingListEntry& ReadingListModelMemory::AddEntry(
ReadingListWillAddUnreadEntry(this, entry));
unread_.insert(unread_.begin(), entry);
hasUnseen_ = true;
+ if (storageLayer_ && !IsPerformingBatchUpdates()) {
+ storageLayer_->SavePersistentUnreadList(unread_);
+ storageLayer_->SavePersistentHasUnseen(true);
+ }
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
ReadingListDidApplyChanges(this));
@@ -111,7 +137,21 @@ void ReadingListModelMemory::MarkReadByURL(const GURL& url) {
read_.insert(read_.begin(), *result);
unread_.erase(result);
+ if (storageLayer_ && !IsPerformingBatchUpdates()) {
+ storageLayer_->SavePersistentUnreadList(unread_);
+ storageLayer_->SavePersistentReadList(read_);
+ }
FOR_EACH_OBSERVER(ReadingListModelObserver, observers_,
ReadingListDidApplyChanges(this));
}
+
+void ReadingListModelMemory::EndBatchUpdates() {
+ ReadingListModel::EndBatchUpdates();
+ if (IsPerformingBatchUpdates() || !storageLayer_) {
+ return;
+ }
+ storageLayer_->SavePersistentUnreadList(unread_);
+ storageLayer_->SavePersistentReadList(read_);
+ storageLayer_->SavePersistentHasUnseen(hasUnseen_);
+}
diff --git a/ios/chrome/browser/reading_list/reading_list_model_memory.h b/ios/chrome/browser/reading_list/reading_list_model_memory.h
index bec14c4..584fba8 100644
--- a/ios/chrome/browser/reading_list/reading_list_model_memory.h
+++ b/ios/chrome/browser/reading_list/reading_list_model_memory.h
@@ -5,14 +5,25 @@
#ifndef IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_MEMORY_H_
#define IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_MEMORY_H_
+#include "base/memory/scoped_ptr.h"
#include "components/keyed_service/core/keyed_service.h"
#include "ios/chrome/browser/reading_list/reading_list_entry.h"
#include "ios/chrome/browser/reading_list/reading_list_model.h"
+class ReadingListModelStorage;
+
// Concrete implementation of a reading list model using in memory lists.
class ReadingListModelMemory : public ReadingListModel, public KeyedService {
public:
+ // Initialize a ReadingListModelMemory to load and save data in
+ // |persistence_layer|.
+ ReadingListModelMemory(
+ std::unique_ptr<ReadingListModelStorage> storage_layer);
+
+ // Initialize a ReadingListModelMemory without persistence. Data will not be
+ // persistent across sessions.
ReadingListModelMemory();
+
~ReadingListModelMemory() override;
void Shutdown() override;
@@ -35,9 +46,13 @@ class ReadingListModelMemory : public ReadingListModel, public KeyedService {
void MarkReadByURL(const GURL& url) override;
+ protected:
+ void EndBatchUpdates() override;
+
private:
std::vector<ReadingListEntry> unread_;
std::vector<ReadingListEntry> read_;
+ std::unique_ptr<ReadingListModelStorage> storageLayer_;
bool hasUnseen_;
bool loaded_;
};
diff --git a/ios/chrome/browser/reading_list/reading_list_model_storage.h b/ios/chrome/browser/reading_list/reading_list_model_storage.h
new file mode 100644
index 0000000..94f4a02
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_model_storage.h
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_STORAGE_H_
+#define IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_STORAGE_H_
+
+#include "ios/chrome/browser/reading_list/reading_list_entry.h"
+
+class ReadingListModel;
+
+// Interface for a persistence layer for reading list.
+// All interface methods have to be called on main thread.
+class ReadingListModelStorage {
+ public:
+ virtual std::vector<ReadingListEntry> LoadPersistentReadList() = 0;
+ virtual std::vector<ReadingListEntry> LoadPersistentUnreadList() = 0;
+ virtual bool LoadPersistentHasUnseen() = 0;
+
+ virtual void SavePersistentReadList(
+ const std::vector<ReadingListEntry>& read) = 0;
+ virtual void SavePersistentUnreadList(
+ const std::vector<ReadingListEntry>& unread) = 0;
+ virtual void SavePersistentHasUnseen(bool has_unseen) = 0;
+};
+
+#endif // IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_STORAGE_H_ \ No newline at end of file
diff --git a/ios/chrome/browser/reading_list/reading_list_model_storage_defaults.h b/ios/chrome/browser/reading_list/reading_list_model_storage_defaults.h
new file mode 100644
index 0000000..1f4fc1b
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_model_storage_defaults.h
@@ -0,0 +1,28 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_STORAGE_DEFAULTS_H_
+#define IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_STORAGE_DEFAULTS_H_
+
+#include "ios/chrome/browser/reading_list/reading_list_entry.h"
+#include "ios/chrome/browser/reading_list/reading_list_model_storage.h"
+
+class ReadingListModel;
+
+// Implementation of ReadingListModelStorage that stores reading list items in
+// the system user defaults.
+class ReadingListModelStorageDefaults : public ReadingListModelStorage {
+ public:
+ std::vector<ReadingListEntry> LoadPersistentReadList() override;
+ std::vector<ReadingListEntry> LoadPersistentUnreadList() override;
+ bool LoadPersistentHasUnseen() override;
+
+ void SavePersistentReadList(
+ const std::vector<ReadingListEntry>& read) override;
+ void SavePersistentUnreadList(
+ const std::vector<ReadingListEntry>& unread) override;
+ void SavePersistentHasUnseen(bool has_unseen) override;
+};
+
+#endif // IOS_CHROME_BROWSER_READING_LIST_READING_LIST_MODEL_STORAGE_DEFAULTS_H_ \ No newline at end of file
diff --git a/ios/chrome/browser/reading_list/reading_list_model_storage_defaults.mm b/ios/chrome/browser/reading_list/reading_list_model_storage_defaults.mm
new file mode 100644
index 0000000..8c16429
--- /dev/null
+++ b/ios/chrome/browser/reading_list/reading_list_model_storage_defaults.mm
@@ -0,0 +1,103 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Foundation/Foundation.h>
+
+#include "ios/chrome/browser/reading_list/reading_list_model_storage_defaults.h"
+
+#include "base/mac/foundation_util.h"
+#include "base/strings/sys_string_conversions.h"
+#import "net/base/mac/url_conversions.h"
+
+namespace {
+
+NSString* const kReadingListReadElements = @"ReadingListReadElements";
+NSString* const kReadingListUnreadElements = @"ReadingListUnreadElements";
+NSString* const kReadingListUnseenState = @"ReadingListUnseenState";
+NSString* const kReadingListEntryTitleKey = @"title";
+NSString* const kReadingListEntryURLKey = @"URL";
+
+ReadingListEntry DecodeReadingListEntry(NSData* data) {
+ NSError* error = nil;
+ NSDictionary* dictionary =
+ [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:data error:&error];
+ NSString* title = base::mac::ObjCCastStrict<NSString>(
+ [dictionary objectForKey:kReadingListEntryTitleKey]);
+ NSURL* url = base::mac::ObjCCastStrict<NSURL>(
+ [dictionary objectForKey:kReadingListEntryURLKey]);
+ DCHECK(title && url);
+ GURL gurl(net::GURLWithNSURL(url));
+ DCHECK(gurl.is_valid());
+ return ReadingListEntry(gurl, base::SysNSStringToUTF8(title));
+}
+
+NSData* EncodeReadingListEntry(const ReadingListEntry& entry) {
+ NSDictionary* dictionary = @{
+ kReadingListEntryTitleKey : base::SysUTF8ToNSString(entry.title()),
+ kReadingListEntryURLKey : net::NSURLWithGURL(entry.url())
+ };
+ return [NSKeyedArchiver archivedDataWithRootObject:dictionary];
+}
+
+} // namespace
+
+std::vector<ReadingListEntry>
+ReadingListModelStorageDefaults::LoadPersistentReadList() {
+ std::vector<ReadingListEntry> read;
+ NSArray* readList =
+ base::mac::ObjCCastStrict<NSArray>([[NSUserDefaults standardUserDefaults]
+ objectForKey:kReadingListReadElements]);
+ if (readList) {
+ for (NSData* entryData : readList) {
+ read.push_back(DecodeReadingListEntry(entryData));
+ }
+ }
+ return read;
+}
+
+std::vector<ReadingListEntry>
+ReadingListModelStorageDefaults::LoadPersistentUnreadList() {
+ std::vector<ReadingListEntry> unread;
+ NSArray* unreadList =
+ base::mac::ObjCCastStrict<NSArray>([[NSUserDefaults standardUserDefaults]
+ objectForKey:kReadingListUnreadElements]);
+ if (unreadList) {
+ for (NSData* entryData : unreadList) {
+ unread.push_back(DecodeReadingListEntry(entryData));
+ }
+ }
+ return unread;
+}
+
+bool ReadingListModelStorageDefaults::LoadPersistentHasUnseen() {
+ return [[[NSUserDefaults standardUserDefaults]
+ objectForKey:kReadingListUnseenState] boolValue];
+}
+
+void ReadingListModelStorageDefaults::SavePersistentReadList(
+ const std::vector<ReadingListEntry>& read) {
+ NSMutableArray* read_list = [NSMutableArray arrayWithCapacity:read.size()];
+ for (const ReadingListEntry& entry : read) {
+ [read_list addObject:EncodeReadingListEntry(entry)];
+ }
+ [[NSUserDefaults standardUserDefaults] setObject:read_list
+ forKey:kReadingListReadElements];
+}
+
+void ReadingListModelStorageDefaults::SavePersistentUnreadList(
+ const std::vector<ReadingListEntry>& unread) {
+ NSMutableArray* unread_list =
+ [NSMutableArray arrayWithCapacity:unread.size()];
+ for (const ReadingListEntry& entry : unread) {
+ [unread_list addObject:EncodeReadingListEntry(entry)];
+ }
+ [[NSUserDefaults standardUserDefaults] setValue:unread_list
+ forKey:kReadingListUnreadElements];
+}
+
+void ReadingListModelStorageDefaults::SavePersistentHasUnseen(bool has_unseen) {
+ [[NSUserDefaults standardUserDefaults]
+ setObject:[NSNumber numberWithBool:has_unseen]
+ forKey:kReadingListUnseenState];
+}
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp
index 50d18a7..ac2fe3a 100644
--- a/ios/chrome/ios_chrome.gyp
+++ b/ios/chrome/ios_chrome.gyp
@@ -450,6 +450,9 @@
'browser/reading_list/reading_list_model_memory.cc',
'browser/reading_list/reading_list_model_memory.h',
'browser/reading_list/reading_list_model_observer.h',
+ 'browser/reading_list/reading_list_model_storage.h',
+ 'browser/reading_list/reading_list_model_storage_defaults.h',
+ 'browser/reading_list/reading_list_model_storage_defaults.mm',
'browser/search/search_util.h',
'browser/search/search_util.mm',
'browser/search_engines/search_engines_util.cc',