summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/app_notification.cc46
-rw-r--r--chrome/browser/extensions/app_notification.h18
-rw-r--r--chrome/browser/extensions/app_notification_manager.cc422
-rw-r--r--chrome/browser/extensions/app_notification_manager.h97
-rw-r--r--chrome/browser/extensions/app_notification_manager_sync_unittest.cc588
-rw-r--r--chrome/browser/extensions/app_notification_manager_unittest.cc18
-rw-r--r--chrome/browser/extensions/app_notification_storage_unittest.cc10
-rw-r--r--chrome/browser/extensions/app_notification_test_util.cc18
-rw-r--r--chrome/browser/extensions/app_notification_test_util.h9
-rw-r--r--chrome/browser/extensions/extension_app_api.cc5
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/chrome_notification_types.h4
12 files changed, 94 insertions, 1142 deletions
diff --git a/chrome/browser/extensions/app_notification.cc b/chrome/browser/extensions/app_notification.cc
index 2dbae2b..f8e60e3 100644
--- a/chrome/browser/extensions/app_notification.cc
+++ b/chrome/browser/extensions/app_notification.cc
@@ -5,13 +5,15 @@
#include "chrome/browser/extensions/app_notification.h"
#include "base/memory/scoped_ptr.h"
-#include "chrome/common/guid.h"
+
+AppNotification::AppNotification(const std::string& title,
+ const std::string& body)
+ : title_(title), body_(body) {}
+
+AppNotification::~AppNotification() {}
namespace {
-const char* kIsLocalKey = "is_local";
-const char* kGuidKey = "guid";
-const char* kExtensionIdKey = "extension_id";
const char* kTitleKey = "title";
const char* kBodyKey = "body";
const char* kLinkUrlKey = "link_url";
@@ -19,27 +21,8 @@ const char* kLinkTextKey = "link_text";
} // namespace
-AppNotification::AppNotification(bool is_local,
- const std::string& guid,
- const std::string& extension_id,
- const std::string& title,
- const std::string& body)
- : is_local_(is_local),
- extension_id_(extension_id),
- title_(title),
- body_(body) {
- guid_ = guid.empty() ? guid::GenerateGUID() : guid;
-}
-
-AppNotification::~AppNotification() {}
-
void AppNotification::ToDictionaryValue(DictionaryValue* result) {
CHECK(result);
- result->SetBoolean(kIsLocalKey, is_local_);
- if (!guid_.empty())
- result->SetString(kGuidKey, guid_);
- if (!extension_id_.empty())
- result->SetString(kExtensionIdKey, extension_id_);
if (!title_.empty())
result->SetString(kTitleKey, title_);
if (!body_.empty())
@@ -53,17 +36,9 @@ void AppNotification::ToDictionaryValue(DictionaryValue* result) {
// static
AppNotification* AppNotification::FromDictionaryValue(
const DictionaryValue& value) {
- scoped_ptr<AppNotification> result(new AppNotification(true, "", "", "", ""));
- if (value.HasKey(kIsLocalKey) && !value.GetBoolean(
- kIsLocalKey, &result->is_local_)) {
- return NULL;
- }
- if (value.HasKey(kGuidKey) && !value.GetString(kGuidKey, &result->guid_))
- return NULL;
- if (value.HasKey(kExtensionIdKey) &&
- !value.GetString(kExtensionIdKey, &result->extension_id_))
- return NULL;
+ scoped_ptr<AppNotification> result(new AppNotification("", ""));
+
if (value.HasKey(kTitleKey) && !value.GetString(kTitleKey, &result->title_))
return NULL;
if (value.HasKey(kBodyKey) && !value.GetString(kBodyKey, &result->body_))
@@ -85,10 +60,7 @@ AppNotification* AppNotification::FromDictionaryValue(
}
bool AppNotification::Equals(const AppNotification& other) const {
- return (is_local_ == other.is_local_ &&
- guid_ == other.guid_ &&
- extension_id_ == other.extension_id_ &&
- title_ == other.title_ &&
+ return (title_ == other.title_ &&
body_ == other.body_ &&
link_url_ == other.link_url_ &&
link_text_ == other.link_text_);
diff --git a/chrome/browser/extensions/app_notification.h b/chrome/browser/extensions/app_notification.h
index 4a9deb6..8fd7743 100644
--- a/chrome/browser/extensions/app_notification.h
+++ b/chrome/browser/extensions/app_notification.h
@@ -17,14 +17,7 @@
// displayed on the New Tab Page.
class AppNotification {
public:
- // Creates an instance with the given properties.
- // If |is_local| is true, notification is not synced.
- // If |guid| is empty, a new guid is automatically created.
- AppNotification(bool is_local,
- const std::string& guid,
- const std::string& extension_id,
- const std::string& title,
- const std::string& body);
+ AppNotification(const std::string& title, const std::string& body);
~AppNotification();
// Setters for optional properties.
@@ -32,9 +25,6 @@ class AppNotification {
void set_link_text(const std::string& text) { link_text_ = text; }
// Accessors.
- bool is_local() const { return is_local_; }
- const std::string& guid() const { return guid_; }
- const std::string& extension_id() const { return extension_id_; }
const std::string& title() const { return title_; }
const std::string& body() const { return body_; }
const GURL& link_url() const { return link_url_; }
@@ -51,12 +41,6 @@ class AppNotification {
// If you add to the list of data members, make sure to add appropriate checks
// to the Equals and {To,From}DictionaryValue methods, keeping in mind
// backwards compatibility.
-
- // Whether notification is local only, which means it is not synced
- // across machines.
- bool is_local_;
- std::string guid_;
- std::string extension_id_;
std::string title_;
std::string body_;
GURL link_url_;
diff --git a/chrome/browser/extensions/app_notification_manager.cc b/chrome/browser/extensions/app_notification_manager.cc
index 53b753d4..01a2bbc 100644
--- a/chrome/browser/extensions/app_notification_manager.cc
+++ b/chrome/browser/extensions/app_notification_manager.cc
@@ -4,75 +4,31 @@
#include "chrome/browser/extensions/app_notification_manager.h"
-#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/file_path.h"
-#include "base/location.h"
#include "base/stl_util.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/protocol/app_notification_specifics.pb.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/extensions/extension.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_service.h"
-typedef std::map<std::string, SyncData> SyncDataMap;
+AppNotificationManager::AppNotificationManager(Profile* profile)
+ : profile_(profile) {
+ registrar_.Add(this,
+ chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
+ Source<Profile>(profile_));
+}
namespace {
-class GuidComparator
- : public std::binary_function<linked_ptr<AppNotification>,
- std::string,
- bool> {
- public:
- bool operator() (linked_ptr<AppNotification> notif,
- const std::string& guid) const {
- return notif->guid() == guid;
- }
-};
-
void DeleteStorageOnFileThread(AppNotificationStorage* storage) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
delete storage;
}
-const AppNotification* FindByGuid(const AppNotificationList& list,
- const std::string& guid) {
- AppNotificationList::const_iterator iter = std::find_if(
- list.begin(), list.end(), std::bind2nd(GuidComparator(), guid));
- return iter == list.end() ? NULL : iter->get();
-}
-
-void RemoveByGuid(AppNotificationList* list, const std::string& guid) {
- if (!list)
- return;
-
- AppNotificationList::iterator iter = std::find_if(
- list->begin(), list->end(), std::bind2nd(GuidComparator(), guid));
- if (iter != list->end())
- list->erase(iter);
-}
-
-void PopulateGuidToSyncDataMap(const SyncDataList& sync_data,
- SyncDataMap* data_map) {
- for (SyncDataList::const_iterator iter = sync_data.begin();
- iter != sync_data.end(); ++iter) {
- (*data_map)[iter->GetSpecifics().GetExtension(
- sync_pb::app_notification).guid()] = *iter;
- }
-}
} // namespace
-AppNotificationManager::AppNotificationManager(Profile* profile)
- : profile_(profile),
- sync_processor_(NULL),
- models_associated_(false),
- processing_syncer_changes_(false) {
- registrar_.Add(this,
- chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
- Source<Profile>(profile_));
-}
-
AppNotificationManager::~AppNotificationManager() {
// Post a task to delete our storage on the file thread.
BrowserThread::PostTask(
@@ -86,79 +42,59 @@ void AppNotificationManager::Init() {
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
- base::Bind(&AppNotificationManager::LoadOnFileThread,
- this, storage_path));
+ base::Bind(
+ &AppNotificationManager::LoadOnFileThread, this, storage_path));
}
-bool AppNotificationManager::Add(AppNotification* item) {
- // Use a scoped_ptr to delete in error paths.
- scoped_ptr<AppNotification> scoped_item(item);
- if (!loaded())
- return false;
- const std::string& extension_id = item->extension_id();
- AppNotificationList& list = GetAllInternal(extension_id);
- linked_ptr<AppNotification> linked_item(scoped_item.release());
- list.push_back(linked_ptr<AppNotification>(linked_item));
+void AppNotificationManager::Add(const std::string& extension_id,
+ AppNotification* item) {
+ NotificationMap::iterator found = notifications_.find(extension_id);
+ if (found == notifications_.end()) {
+ notifications_[extension_id] = AppNotificationList();
+ found = notifications_.find(extension_id);
+ }
+ CHECK(found != notifications_.end());
+ AppNotificationList& list = (*found).second;
+ list.push_back(linked_ptr<AppNotification>(item));
- SyncAddChange(*linked_item);
+ if (!storage_.get())
+ return;
- if (storage_.get()) {
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&AppNotificationManager::SaveOnFileThread,
- this, extension_id, list));
- }
- return true;
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(
+ &AppNotificationManager::SaveOnFileThread, this, extension_id, list));
}
const AppNotificationList* AppNotificationManager::GetAll(
- const std::string& extension_id) const {
- if (!loaded())
- return NULL;
- if (ContainsKey(*notifications_, extension_id))
- return &((*notifications_)[extension_id]);
- return NULL;
-}
-
-AppNotificationList& AppNotificationManager::GetAllInternal(
const std::string& extension_id) {
- NotificationMap::iterator found = notifications_->find(extension_id);
- if (found == notifications_->end()) {
- (*notifications_)[extension_id] = AppNotificationList();
- found = notifications_->find(extension_id);
- }
- CHECK(found != notifications_->end());
- return found->second;
+ if (ContainsKey(notifications_, extension_id))
+ return &notifications_[extension_id];
+ return NULL;
}
const AppNotification* AppNotificationManager::GetLast(
const std::string& extension_id) {
- if (!loaded())
- return NULL;
- NotificationMap::iterator found = notifications_->find(extension_id);
- if (found == notifications_->end())
+ NotificationMap::iterator found = notifications_.find(extension_id);
+ if (found == notifications_.end())
return NULL;
const AppNotificationList& list = found->second;
return list.rbegin()->get();
}
void AppNotificationManager::ClearAll(const std::string& extension_id) {
- if (!loaded())
- return;
- NotificationMap::iterator found = notifications_->find(extension_id);
- if (found != notifications_->end()) {
- SyncClearAllChange(found->second);
- notifications_->erase(found);
- }
+ NotificationMap::iterator found = notifications_.find(extension_id);
+ if (found != notifications_.end())
+ notifications_.erase(found);
- if (storage_.get()) {
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&AppNotificationManager::DeleteOnFileThread,
- this, extension_id));
- }
+ if (!storage_.get())
+ return;
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(
+ &AppNotificationManager::DeleteOnFileThread, this, extension_id));
}
void AppNotificationManager::Observe(int type,
@@ -170,53 +106,43 @@ void AppNotificationManager::Observe(int type,
void AppNotificationManager::LoadOnFileThread(const FilePath& storage_path) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- DCHECK(!loaded());
storage_.reset(AppNotificationStorage::Create(storage_path));
if (!storage_.get())
return;
- scoped_ptr<NotificationMap> result(new NotificationMap());
+ NotificationMap result;
std::set<std::string> ids;
if (!storage_->GetExtensionIds(&ids))
return;
std::set<std::string>::const_iterator i;
for (i = ids.begin(); i != ids.end(); ++i) {
const std::string& id = *i;
- AppNotificationList& list = (*result)[id];
+ AppNotificationList& list = result[id];
if (!storage_->Get(id, &list))
- result->erase(id);
+ result.erase(id);
}
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
- base::Bind(&AppNotificationManager::HandleLoadResults,
- this, result.release()));
+ base::Bind(&AppNotificationManager::HandleLoadResults, this, result));
}
-void AppNotificationManager::HandleLoadResults(NotificationMap* map) {
+void AppNotificationManager::HandleLoadResults(const NotificationMap& map) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(map);
- DCHECK(!loaded());
- notifications_.reset(map);
-
- // Generate STATE_CHAGNED notifications for extensions that have at
- // least one notification loaded.
NotificationMap::const_iterator i;
- for (i = map->begin(); i != map->end(); ++i) {
+ for (i = map.begin(); i != map.end(); ++i) {
const std::string& id = i->first;
- if (i->second.empty())
+ const AppNotificationList& list = i->second;
+ if (list.empty())
continue;
+ notifications_[id].insert(notifications_[id].begin(),
+ list.begin(),
+ list.end());
NotificationService::current()->Notify(
chrome::NOTIFICATION_APP_NOTIFICATION_STATE_CHANGED,
Source<Profile>(profile_),
Details<const std::string>(&id));
}
-
- // Generate MANAGER_LOADED notification.
- NotificationService::current()->Notify(
- chrome::NOTIFICATION_APP_NOTIFICATION_MANAGER_LOADED,
- Source<AppNotificationManager>(this),
- NotificationService::NoDetails());
}
void AppNotificationManager::SaveOnFileThread(const std::string& extension_id,
@@ -230,249 +156,3 @@ void AppNotificationManager::DeleteOnFileThread(
CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
storage_->Delete(extension_id);
}
-
-SyncDataList AppNotificationManager::GetAllSyncData(
- syncable::ModelType type) const {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(loaded());
- DCHECK_EQ(syncable::APP_NOTIFICATIONS, type);
- SyncDataList data;
- for (NotificationMap::const_iterator iter = notifications_->begin();
- iter != notifications_->end(); ++iter) {
-
- // Skip local notifications since they should not be synced.
- const AppNotificationList list = (*iter).second;
- for (AppNotificationList::const_iterator list_iter = list.begin();
- list_iter != list.end(); ++list_iter) {
- const AppNotification* notification = (*list_iter).get();
- if (notification->is_local()) {
- continue;
- }
- data.push_back(CreateSyncDataFromNotification(*notification));
- }
- }
-
- return data;
-}
-
-SyncError AppNotificationManager::ProcessSyncChanges(
- const tracked_objects::Location& from_here,
- const SyncChangeList& change_list) {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(loaded());
- if (!models_associated_)
- return SyncError(FROM_HERE, "Models not yet associated.",
- syncable::APP_NOTIFICATIONS);
-
- AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
-
- SyncError error;
- for (SyncChangeList::const_iterator iter = change_list.begin();
- iter != change_list.end(); ++iter) {
- SyncData sync_data = iter->sync_data();
- DCHECK_EQ(syncable::APP_NOTIFICATIONS, sync_data.GetDataType());
- SyncChange::SyncChangeType change_type = iter->change_type();
-
- scoped_ptr<AppNotification> new_notif(CreateNotificationFromSyncData(
- sync_data));
- if (!new_notif.get()) {
- NOTREACHED() << "Failed to read notification.";
- continue;
- }
- const AppNotification* existing_notif = GetNotification(
- new_notif->extension_id(), new_notif->guid());
- if (existing_notif && existing_notif->is_local()) {
- NOTREACHED() << "Matched with notification marked as local";
- error = SyncError(FROM_HERE,
- "ProcessSyncChanges received a local only notification" +
- SyncChange::ChangeTypeToString(change_type),
- syncable::APP_NOTIFICATIONS);
- continue;
- }
-
- if (change_type == SyncChange::ACTION_ADD && !existing_notif) {
- Add(new_notif.release());
- } else if (change_type == SyncChange::ACTION_DELETE && existing_notif) {
- Remove(existing_notif->extension_id(), existing_notif->guid());
- } else {
- // Something really unexpected happened. Either we received an
- // ACTION_INVALID, or Sync is in a crazy state:
- // - Trying to UPDATE: notifications are immutable.
- // . Trying to DELETE a non-existent item.
- // - Trying to ADD an item that already exists.
- NOTREACHED() << "Unexpected sync change state.";
- error = SyncError(FROM_HERE, "ProcessSyncChanges failed on ChangeType " +
- SyncChange::ChangeTypeToString(change_type),
- syncable::APP_NOTIFICATIONS);
- continue;
- }
- }
-
- return error;
-}
-
-SyncError AppNotificationManager::MergeDataAndStartSyncing(
- syncable::ModelType type,
- const SyncDataList& initial_sync_data,
- SyncChangeProcessor* sync_processor) {
- CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // AppNotificationDataTypeController ensures that modei is fully should before
- // this method is called by waiting until the load notification is received
- // from AppNotificationManager.
- DCHECK(loaded());
- DCHECK_EQ(type, syncable::APP_NOTIFICATIONS);
- DCHECK(!sync_processor_);
- sync_processor_ = sync_processor;
-
- // We may add, or remove notifications here, so ensure we don't step on
- // our own toes.
- AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
-
- SyncDataMap local_data_map;
- PopulateGuidToSyncDataMap(GetAllSyncData(syncable::APP_NOTIFICATIONS),
- &local_data_map);
-
- for (SyncDataList::const_iterator iter = initial_sync_data.begin();
- iter != initial_sync_data.end(); ++iter) {
- const SyncData& sync_data = *iter;
- DCHECK_EQ(syncable::APP_NOTIFICATIONS, sync_data.GetDataType());
- scoped_ptr<AppNotification> sync_notif(CreateNotificationFromSyncData(
- sync_data));
- CHECK(sync_notif.get());
- const AppNotification* local_notif = GetNotification(
- sync_notif->extension_id(), sync_notif->guid());
- if (local_notif) {
- local_data_map.erase(sync_notif->guid());
- // Local notification should always match with sync notification as
- // notifications are immutable.
- if (local_notif->is_local() || !sync_notif->Equals(*local_notif)) {
- return SyncError(FROM_HERE,
- "MergeDataAndStartSyncing failed: local notification and sync "
- "notification have same guid but different data.",
- syncable::APP_NOTIFICATIONS);
- }
- } else {
- // Sync model has a notification that local model does not, add it.
- Add(sync_notif.release());
- }
- }
-
- // TODO(munjal): crbug.com/10059. Work with Lingesh/Antony to resolve.
- SyncChangeList new_changes;
- for (SyncDataMap::const_iterator iter = local_data_map.begin();
- iter != local_data_map.end(); ++iter) {
- new_changes.push_back(SyncChange(SyncChange::ACTION_ADD, iter->second));
- }
-
- SyncError error;
- if (new_changes.size() > 0)
- error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes);
- models_associated_ = !error.IsSet();
- return error;
-}
-
-void AppNotificationManager::StopSyncing(syncable::ModelType type) {
- DCHECK_EQ(type, syncable::APP_NOTIFICATIONS);
- models_associated_ = false;
- sync_processor_ = NULL;
-}
-
-void AppNotificationManager::SyncAddChange(const AppNotification& notif) {
- // Skip if either:
- // - Notification is marked as local.
- // - Sync is not enabled by user.
- // - Change is generated from within the manager.
- if (notif.is_local() || !models_associated_ || processing_syncer_changes_)
- return;
-
- // TODO(munjal): crbug.com/10059. Work with Lingesh/Antony to resolve.
-
- SyncChangeList changes;
- SyncData sync_data = CreateSyncDataFromNotification(notif);
- changes.push_back(SyncChange(SyncChange::ACTION_ADD, sync_data));
- sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
-}
-
-void AppNotificationManager::SyncClearAllChange(
- const AppNotificationList& list) {
- // Skip if either:
- // - Sync is not enabled by user.
- // - Change is generated from within the manager.
- if (!models_associated_ || processing_syncer_changes_)
- return;
-
- SyncChangeList changes;
- for (AppNotificationList::const_iterator iter = list.begin();
- iter != list.end(); ++iter) {
- const AppNotification& notif = *iter->get();
- // Skip notifications marked as local.
- if (notif.is_local())
- continue;
- changes.push_back(SyncChange(
- SyncChange::ACTION_DELETE,
- CreateSyncDataFromNotification(notif)));
- }
- sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
-}
-
-const AppNotification* AppNotificationManager::GetNotification(
- const std::string& extension_id, const std::string& guid) {
- DCHECK(loaded());
- const AppNotificationList& list = GetAllInternal(extension_id);
- return FindByGuid(list, guid);
-}
-
-void AppNotificationManager::Remove(const std::string& extension_id,
- const std::string& guid) {
- DCHECK(loaded());
- AppNotificationList& list = GetAllInternal(extension_id);
- RemoveByGuid(&list, guid);
-
- if (storage_.get()) {
- BrowserThread::PostTask(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&AppNotificationManager::SaveOnFileThread,
- this, extension_id, list));
- }
-}
-
-// static
-SyncData AppNotificationManager::CreateSyncDataFromNotification(
- const AppNotification& notification) {
- DCHECK(!notification.is_local());
- sync_pb::EntitySpecifics specifics;
- sync_pb::AppNotificationSpecifics* notif_specifics =
- specifics.MutableExtension(sync_pb::app_notification);
- notif_specifics->set_app_id(notification.extension_id());
- notif_specifics->set_body_text(notification.body());
- notif_specifics->set_guid(notification.guid());
- notif_specifics->set_link_text(notification.link_text());
- notif_specifics->set_link_url(notification.link_url().spec());
- notif_specifics->set_title(notification.title());
-
- return SyncData::CreateLocalData(
- notif_specifics->guid(), notif_specifics->app_id(), specifics);
-}
-
-// static
-AppNotification* AppNotificationManager::CreateNotificationFromSyncData(
- const SyncData& sync_data) {
- sync_pb::AppNotificationSpecifics specifics =
- sync_data.GetSpecifics().GetExtension(sync_pb::app_notification);
-
- // Check for mandatory fields.
- if (!specifics.has_app_id() || !specifics.has_guid() ||
- !specifics.has_title() || !specifics.has_body_text()) {
- return NULL;
- }
-
- AppNotification* notification = new AppNotification(
- false, specifics.guid(), specifics.app_id(),
- specifics.title(), specifics.body_text());
- if (specifics.has_link_text())
- notification->set_link_text(specifics.link_text());
- if (specifics.has_link_url())
- notification->set_link_url(GURL(specifics.link_url()));
- return notification;
-}
diff --git a/chrome/browser/extensions/app_notification_manager.h b/chrome/browser/extensions/app_notification_manager.h
index 7c37cc7..8148a08 100644
--- a/chrome/browser/extensions/app_notification_manager.h
+++ b/chrome/browser/extensions/app_notification_manager.h
@@ -9,15 +9,10 @@
#include <map>
#include "base/compiler_specific.h"
-#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/waitable_event.h"
#include "chrome/browser/extensions/app_notification.h"
#include "chrome/browser/extensions/app_notification_storage.h"
-#include "chrome/browser/sync/api/sync_change.h"
-#include "chrome/browser/sync/api/syncable_service.h"
-#include "content/common/notification_details.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"
@@ -26,20 +21,17 @@ class Profile;
// This class keeps track of notifications for installed apps.
class AppNotificationManager
: public base::RefCountedThreadSafe<AppNotificationManager>,
- public NotificationObserver,
- public SyncableService {
+ public NotificationObserver {
public:
explicit AppNotificationManager(Profile* profile);
- virtual ~AppNotificationManager();
// Starts up the process of reading from persistent storage.
void Init();
- // Returns whether add was succcessful.
- // Takes ownership of |item| in all cases.
- bool Add(AppNotification* item);
+ // Takes ownership of |notification|.
+ void Add(const std::string& extension_id, AppNotification* item);
- const AppNotificationList* GetAll(const std::string& extension_id) const;
+ const AppNotificationList* GetAll(const std::string& extension_id);
// Returns the most recently added notification for |extension_id| if there
// are any, or NULL otherwise.
@@ -53,105 +45,32 @@ class AppNotificationManager
const NotificationSource& source,
const NotificationDetails& details) OVERRIDE;
- bool loaded() const { return notifications_.get() != NULL; }
-
- // SyncableService implementation.
-
- // Returns all syncable notifications from this model as SyncData.
- virtual SyncDataList GetAllSyncData(syncable::ModelType type) const OVERRIDE;
- // Process notifications related changes from Sync, merging them into
- // our model.
- virtual SyncError ProcessSyncChanges(
- const tracked_objects::Location& from_here,
- const SyncChangeList& change_list) OVERRIDE;
- // Associate and merge sync data model with our data model.
- virtual SyncError MergeDataAndStartSyncing(
- syncable::ModelType type,
- const SyncDataList& initial_sync_data,
- SyncChangeProcessor* sync_processor) OVERRIDE;
- virtual void StopSyncing(syncable::ModelType type) OVERRIDE;
-
private:
- friend class AppNotificationManagerSyncTest;
- FRIEND_TEST_ALL_PREFIXES(AppNotificationManagerSyncTest,
- NotificationToSyncDataToNotification);
- FRIEND_TEST_ALL_PREFIXES(AppNotificationManagerSyncTest,
- GetAllSyncDataNoLocal);
- FRIEND_TEST_ALL_PREFIXES(AppNotificationManagerSyncTest,
- GetAllSyncDataSomeLocal);
- FRIEND_TEST_ALL_PREFIXES(AppNotificationManagerSyncTest,
- ModelAssocModelEmpty);
- FRIEND_TEST_ALL_PREFIXES(AppNotificationManagerSyncTest,
- ModelAssocBothNonEmptyNoOverlap);
- FRIEND_TEST_ALL_PREFIXES(AppNotificationManagerSyncTest,
- ModelAssocBothNonEmptySomeOverlap);
- FRIEND_TEST_ALL_PREFIXES(AppNotificationManagerSyncTest,
- ModelAssocBothNonEmptyTitleMismatch);
- FRIEND_TEST_ALL_PREFIXES(AppNotificationManagerSyncTest,
- ModelAssocBothNonEmptyMatchesLocal);
- FRIEND_TEST_ALL_PREFIXES(AppNotificationManagerSyncTest,
- ProcessSyncChangesErrorModelAssocNotDone);
- FRIEND_TEST_ALL_PREFIXES(AppNotificationManagerSyncTest,
- ProcessSyncChangesEmptyModel);
- FRIEND_TEST_ALL_PREFIXES(AppNotificationManagerSyncTest,
- StopSyncing);
- FRIEND_TEST_ALL_PREFIXES(AppNotificationManagerSyncTest,
- ClearAllGetsSynced);
-
friend class base::RefCountedThreadSafe<AppNotificationManager>;
// Maps extension id to a list of notifications for that extension.
typedef std::map<std::string, AppNotificationList> NotificationMap;
+ virtual ~AppNotificationManager();
+
// Starts loading storage_ using |storage_path|.
void LoadOnFileThread(const FilePath& storage_path);
// Called on the UI thread to handle the loaded results from storage_.
- void HandleLoadResults(NotificationMap* map);
+ void HandleLoadResults(const NotificationMap& map);
void SaveOnFileThread(const std::string& extension_id,
const AppNotificationList& list);
void DeleteOnFileThread(const std::string& extension_id);
- // Gets notficiations for a given extension id.
- AppNotificationList& GetAllInternal(const std::string& extension_id);
-
- // Removes the notification with given extension id and given guid.
- void Remove(const std::string& extension_id, const std::string& guid);
-
- // Returns the notification for the given |extension_id| and |guid|,
- // NULL if no such notification exists.
- const AppNotification* GetNotification(const std::string& extension_id,
- const std::string& guid);
-
- // Sends a change to syncer to add the given notification.
- void SyncAddChange(const AppNotification& notif);
-
- // Sends changes to syncer to remove all notifications in the given list.
- void SyncClearAllChange(const AppNotificationList& list);
-
- // Converters from AppNotification to SyncData and vice versa.
- static SyncData CreateSyncDataFromNotification(
- const AppNotification& notification);
- static AppNotification* CreateNotificationFromSyncData(
- const SyncData& sync_data);
-
Profile* profile_;
NotificationRegistrar registrar_;
- scoped_ptr<NotificationMap> notifications_;
+ NotificationMap notifications_;
// This should only be used on the FILE thread.
scoped_ptr<AppNotificationStorage> storage_;
- // Sync change processor we use to push all our changes.
- SyncChangeProcessor* sync_processor_;
- // Whether the sync model is associated with the local model.
- // In other words, whether we are ready to apply sync changes.
- bool models_associated_;
- // Whether syncer changes are being processed right now.
- bool processing_syncer_changes_;
-
DISALLOW_COPY_AND_ASSIGN(AppNotificationManager);
};
diff --git a/chrome/browser/extensions/app_notification_manager_sync_unittest.cc b/chrome/browser/extensions/app_notification_manager_sync_unittest.cc
deleted file mode 100644
index 41589d7..0000000
--- a/chrome/browser/extensions/app_notification_manager_sync_unittest.cc
+++ /dev/null
@@ -1,588 +0,0 @@
-// Copyright (c) 2011 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.
-
-#include "base/bind.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/string_number_conversions.h"
-#include "chrome/browser/extensions/app_notification_manager.h"
-#include "chrome/browser/extensions/app_notification.h"
-#include "chrome/browser/sync/protocol/app_notification_specifics.pb.h"
-#include "chrome/test/base/testing_profile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// Extract notification guid from SyncData.
-std::string GetGuid(const SyncData& sync_data) {
- return sync_data.GetSpecifics().GetExtension(
- sync_pb::app_notification).guid();
-}
-
-// Dummy SyncChangeProcessor used to help review what SyncChanges are pushed
-// back up to Sync.
-class TestChangeProcessor : public SyncChangeProcessor {
- public:
- TestChangeProcessor() { }
- virtual ~TestChangeProcessor() { }
-
- // Store a copy of all the changes passed in so we can examine them later.
- virtual SyncError ProcessSyncChanges(
- const tracked_objects::Location& from_here,
- const SyncChangeList& change_list) {
- // change_map_.erase(change_map_.begin(), change_map_.end());
- for (SyncChangeList::const_iterator iter = change_list.begin();
- iter != change_list.end(); ++iter) {
- change_map_[GetGuid(iter->sync_data())] = *iter;
- }
-
- return SyncError();
- }
-
- bool ContainsGuid(const std::string& guid) {
- return change_map_.find(guid) != change_map_.end();
- }
-
- SyncChange GetChangeByGuid(const std::string& guid) {
- DCHECK(ContainsGuid(guid));
- return change_map_[guid];
- }
-
- int change_list_size() { return change_map_.size(); }
-
- private:
- // Track the changes received in ProcessSyncChanges.
- std::map<std::string, SyncChange> change_map_;
-
- DISALLOW_COPY_AND_ASSIGN(TestChangeProcessor);
-};
-
-} // namespace
-
-class AppNotificationManagerSyncTest : public testing::Test {
- public:
- AppNotificationManagerSyncTest()
- : ui_thread_(BrowserThread::UI, &ui_loop_),
- file_thread_(BrowserThread::FILE) { }
-
- ~AppNotificationManagerSyncTest() {
- model_ = NULL;
- }
-
- virtual void SetUp() {
- ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
- file_thread_.Start();
-
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- profile_.reset(new TestingProfile(temp_dir_.path()));
- model_ = new AppNotificationManager(profile_.get());
- model_->Init();
-
- WaitForFileThread();
- ASSERT_TRUE(model_->loaded());
- }
-
- virtual void TearDown() { }
-
- static void PostQuitToUIThread() {
- BrowserThread::PostTask(BrowserThread::UI,
- FROM_HERE,
- new MessageLoop::QuitTask());
- }
-
- static void WaitForFileThread() {
- BrowserThread::PostTask(BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&PostQuitToUIThread));
- MessageLoop::current()->Run();
- }
-
- AppNotificationManager* model() { return model_.get(); }
- TestChangeProcessor* processor() { return &processor_; }
-
- // Creates a notification whose properties are set from the given integer.
- static AppNotification* CreateNotification(int suffix) {
- return CreateNotification(false, suffix);
- }
- static AppNotification* CreateNotification(bool is_local, int suffix) {
- std::string s = base::IntToString(suffix);
- return CreateNotification(
- is_local, "guid" + s, "ext" + s, "text" + s, "body" + s,
- "http://www.url" + s + ".com", "link text " + s);
- }
- static AppNotification* CreateNotification(
- bool is_local, int suffix, const std::string& extension_id) {
- std::string s = base::IntToString(suffix);
- return CreateNotification(
- is_local, "guid" + s, extension_id, "text" + s, "body" + s,
- "http://www.url" + s + ".com", "link text " + s);
- }
-
- // Creates a notification whose properties are set from the given integer
- // but does not set link url and link text.
- static AppNotification* CreateNotificationNoLink(int suffix) {
- return CreateNotificationNoLink(false, suffix);
- }
- static AppNotification* CreateNotificationNoLink(bool is_local, int suffix) {
- std::string s = base::IntToString(suffix);
- return CreateNotification(
- is_local, "guid" + s, "ext" + s, "text" + s, "body" + s, "", "");
- }
-
- // link_url and link_text are only set if the passed in values are not empty.
- static AppNotification* CreateNotification(bool is_local,
- const std::string& guid,
- const std::string& extension_id,
- const std::string& title,
- const std::string& body,
- const std::string& link_url,
- const std::string& link_text) {
- AppNotification* notif = new AppNotification(
- is_local, guid, extension_id, title, body);
- if (!link_url.empty())
- notif->set_link_url(GURL(link_url));
- if (!link_text.empty())
- notif->set_link_text(link_text);
- return notif;
- }
-
- static AppNotification* CreateNotification(const AppNotification& notif) {
- return CreateNotification(
- notif.is_local(), notif.guid(), notif.extension_id(), notif.title(),
- notif.body(), notif.link_url().spec(), notif.link_text());
- }
-
- static SyncData CreateSyncData(int suffix) {
- scoped_ptr<AppNotification> notif(CreateNotification(suffix));
- return AppNotificationManager::CreateSyncDataFromNotification(*notif);
- }
- static SyncData CreateSyncData(int suffix, const std::string& extension_id) {
- scoped_ptr<AppNotification> notif(
- CreateNotification(false, suffix, extension_id));
- return AppNotificationManager::CreateSyncDataFromNotification(*notif);
- }
-
- // Helper to create SyncChange. Takes ownership of |notif|.
- static SyncChange CreateSyncChange(SyncChange::SyncChangeType type,
- AppNotification* notif) {
- // Take control of notif to clean it up after we create data out of it.
- scoped_ptr<AppNotification> scoped_notif(notif);
- return SyncChange(
- type, AppNotificationManager::CreateSyncDataFromNotification(*notif));
- }
-
- void AssertSyncChange(const SyncChange& change,
- SyncChange::SyncChangeType type,
- const AppNotification& notif) {
- ASSERT_EQ(type, change.change_type());
- const AppNotification* notif2 =
- AppNotificationManager::CreateNotificationFromSyncData(
- change.sync_data());
- ASSERT_TRUE(notif.Equals(*notif2));
- }
-
- protected:
- MessageLoop ui_loop_;
- BrowserThread ui_thread_;
- BrowserThread file_thread_;
-
- // We keep two TemplateURLServices to test syncing between them.
- ScopedTempDir temp_dir_;
- scoped_ptr<TestingProfile> profile_;
- scoped_refptr<AppNotificationManager> model_;
-
- TestChangeProcessor processor_;
-
- DISALLOW_COPY_AND_ASSIGN(AppNotificationManagerSyncTest);
-};
-
-// Create an AppNotification, convert it to SyncData and convert it back.
-TEST_F(AppNotificationManagerSyncTest, NotificationToSyncDataToNotification) {
- { // Partial properties set.
- scoped_ptr<AppNotification> notif1(CreateNotificationNoLink(1));
- SyncData sync_data =
- AppNotificationManager::CreateSyncDataFromNotification(*notif1);
- scoped_ptr<AppNotification> notif2(
- AppNotificationManager::CreateNotificationFromSyncData(sync_data));
- EXPECT_TRUE(notif2.get());
- EXPECT_TRUE(notif1->Equals(*notif2));
- }
- { // All properties set.
- scoped_ptr<AppNotification> notif1(CreateNotification(1));
- SyncData sync_data =
- AppNotificationManager::CreateSyncDataFromNotification(*notif1);
- scoped_ptr<AppNotification> notif2(
- AppNotificationManager::CreateNotificationFromSyncData(sync_data));
- EXPECT_TRUE(notif2.get());
- EXPECT_TRUE(notif1->Equals(*notif2));
- }
-}
-
-// GetAllSyncData returns all notifications since none are marked local only.
-TEST_F(AppNotificationManagerSyncTest, GetAllSyncDataNoLocal) {
- model()->Add(CreateNotificationNoLink(1));
- model()->Add(CreateNotification(2));
- model()->Add(CreateNotification(3));
- SyncDataList all_sync_data =
- model()->GetAllSyncData(syncable::APP_NOTIFICATIONS);
-
- EXPECT_EQ(3U, all_sync_data.size());
-
- for (SyncDataList::const_iterator iter = all_sync_data.begin();
- iter != all_sync_data.end(); ++iter) {
- scoped_ptr<AppNotification> notif1(
- AppNotificationManager::CreateNotificationFromSyncData(*iter));
-
- const std::string& guid = notif1->guid();
- const std::string& ext_id = notif1->extension_id();
-
- const AppNotification* notif2 = model()->GetNotification(ext_id, guid);
- ASSERT_TRUE(notif1->Equals(*notif2));
- }
-}
-
-// GetAllSyncData should not return notifications marked as local only.
-TEST_F(AppNotificationManagerSyncTest, GetAllSyncDataSomeLocal) {
- model()->Add(CreateNotificationNoLink(1));
- model()->Add(CreateNotification(true, 2));
- model()->Add(CreateNotification(3));
- model()->Add(CreateNotification(true, 4));
- model()->Add(CreateNotification(5));
- SyncDataList all_sync_data =
- model()->GetAllSyncData(syncable::APP_NOTIFICATIONS);
-
- EXPECT_EQ(3U, all_sync_data.size());
-
- for (SyncDataList::const_iterator iter = all_sync_data.begin();
- iter != all_sync_data.end(); ++iter) {
- scoped_ptr<AppNotification> notif1(
- AppNotificationManager::CreateNotificationFromSyncData(*iter));
- const std::string& guid = notif1->guid();
- const std::string& ext_id = notif1->extension_id();
-
- const AppNotification* notif2 = model()->GetNotification(ext_id, guid);
- ASSERT_TRUE(notif1->Equals(*notif2));
- }
-}
-
-// Model assocation: both models are empty.
-TEST_F(AppNotificationManagerSyncTest, ModelAssocBothEmpty) {
- model()->MergeDataAndStartSyncing(
- syncable::APP_NOTIFICATIONS,
- SyncDataList(), // Empty.
- processor());
-
- EXPECT_EQ(0U, model()->GetAllSyncData(syncable::APP_NOTIFICATIONS).size());
- EXPECT_EQ(0, processor()->change_list_size());
-}
-
-// Model assocation: empty sync model and non-empty local model.
-TEST_F(AppNotificationManagerSyncTest, ModelAssocModelEmpty) {
- SyncDataList initial_data;
- initial_data.push_back(CreateSyncData(1));
- initial_data.push_back(CreateSyncData(2));
- initial_data.push_back(CreateSyncData(3));
- initial_data.push_back(CreateSyncData(4));
-
- model()->MergeDataAndStartSyncing(
- syncable::APP_NOTIFICATIONS,
- initial_data,
- processor());
-
- EXPECT_EQ(4U, model()->GetAllSyncData(syncable::APP_NOTIFICATIONS).size());
- // Model should all of the initial sync data.
- for (SyncDataList::const_iterator iter = initial_data.begin();
- iter != initial_data.end(); ++iter) {
- scoped_ptr<AppNotification> notif1(
- AppNotificationManager::CreateNotificationFromSyncData(*iter));
- const std::string& ext_id = notif1->extension_id();
- const std::string& guid = notif1->guid();
- const AppNotification* notif2 = model()->GetNotification(ext_id, guid);
- EXPECT_TRUE(notif2);
- EXPECT_TRUE(notif1->Equals(*notif2));
- }
-
- EXPECT_EQ(0, processor()->change_list_size());
-}
-
-// Model has some notifications, some of them are local only. Sync has some
-// notifications. No items match up.
-TEST_F(AppNotificationManagerSyncTest, ModelAssocBothNonEmptyNoOverlap) {
- AppNotification* n1 = CreateNotification(1);
- model()->Add(n1);
- AppNotification* n2 = CreateNotification(true, 2);
- model()->Add(n2);
- AppNotification* n3 = CreateNotification(3);
- model()->Add(n3);
-
- SyncDataList initial_data;
- initial_data.push_back(CreateSyncData(4));
- initial_data.push_back(CreateSyncData(5));
- initial_data.push_back(CreateSyncData(6));
- initial_data.push_back(CreateSyncData(7));
-
- model()->MergeDataAndStartSyncing(
- syncable::APP_NOTIFICATIONS,
- initial_data,
- processor());
-
- EXPECT_EQ(6U, model()->GetAllSyncData(syncable::APP_NOTIFICATIONS).size());
- for (SyncDataList::const_iterator iter = initial_data.begin();
- iter != initial_data.end(); ++iter) {
- scoped_ptr<AppNotification> notif1(
- AppNotificationManager::CreateNotificationFromSyncData(*iter));
- const std::string& ext_id = notif1->extension_id();
- const std::string& guid = notif1->guid();
- const AppNotification* notif2 = model()->GetNotification(ext_id, guid);
- EXPECT_TRUE(notif2);
- EXPECT_TRUE(notif1->Equals(*notif2));
- }
- EXPECT_TRUE(model()->GetNotification(n1->extension_id(), n1->guid()));
- EXPECT_TRUE(model()->GetNotification(n2->extension_id(), n2->guid()));
- EXPECT_TRUE(model()->GetNotification(n3->extension_id(), n3->guid()));
-
- EXPECT_EQ(2, processor()->change_list_size());
- EXPECT_TRUE(processor()->ContainsGuid(n1->guid()));
- EXPECT_EQ(SyncChange::ACTION_ADD,
- processor()->GetChangeByGuid(n1->guid()).change_type());
- EXPECT_FALSE(processor()->ContainsGuid(n2->guid()));
- EXPECT_TRUE(processor()->ContainsGuid(n3->guid()));
- EXPECT_EQ(SyncChange::ACTION_ADD,
- processor()->GetChangeByGuid(n3->guid()).change_type());
-}
-
-// Model has some notifications, some of them are local only. Sync has some
-// notifications. Some items match up.
-TEST_F(AppNotificationManagerSyncTest, ModelAssocBothNonEmptySomeOverlap) {
- AppNotification* n1 = CreateNotification(1);
- model()->Add(n1);
- AppNotification* n2 = CreateNotification(true, 2);
- model()->Add(n2);
- AppNotification* n3 = CreateNotification(3);
- model()->Add(n3);
- AppNotification* n4 = CreateNotification(4);
- model()->Add(n4);
-
- SyncDataList initial_data;
- initial_data.push_back(CreateSyncData(5));
- initial_data.push_back(
- AppNotificationManager::CreateSyncDataFromNotification(*n1));
- initial_data.push_back(CreateSyncData(6));
- initial_data.push_back(
- AppNotificationManager::CreateSyncDataFromNotification(*n4));
- initial_data.push_back(CreateSyncData(7));
-
- model()->MergeDataAndStartSyncing(
- syncable::APP_NOTIFICATIONS,
- initial_data,
- processor());
-
- EXPECT_EQ(6U, model()->GetAllSyncData(syncable::APP_NOTIFICATIONS).size());
- for (SyncDataList::const_iterator iter = initial_data.begin();
- iter != initial_data.end(); ++iter) {
- scoped_ptr<AppNotification> notif1(
- AppNotificationManager::CreateNotificationFromSyncData(*iter));
- const std::string& ext_id = notif1->extension_id();
- const std::string& guid = notif1->guid();
- const AppNotification* notif2 = model()->GetNotification(ext_id, guid);
- EXPECT_TRUE(notif2);
- EXPECT_TRUE(notif1->Equals(*notif2));
- }
- EXPECT_TRUE(model()->GetNotification(n1->extension_id(), n1->guid()));
- EXPECT_TRUE(model()->GetNotification(n2->extension_id(), n2->guid()));
- EXPECT_TRUE(model()->GetNotification(n3->extension_id(), n3->guid()));
- EXPECT_TRUE(model()->GetNotification(n4->extension_id(), n4->guid()));
-
- EXPECT_EQ(1, processor()->change_list_size());
- EXPECT_FALSE(processor()->ContainsGuid(n1->guid()));
- EXPECT_FALSE(processor()->ContainsGuid(n2->guid()));
- EXPECT_TRUE(processor()->ContainsGuid(n3->guid()));
- EXPECT_EQ(SyncChange::ACTION_ADD,
- processor()->GetChangeByGuid(n3->guid()).change_type());
- EXPECT_FALSE(processor()->ContainsGuid(n4->guid()));
-}
-
-// When an item that matches up in model and sync is different, an error
-// should be returned.
-TEST_F(AppNotificationManagerSyncTest, ModelAssocBothNonEmptyTitleMismatch) {
- AppNotification* n1 = CreateNotification(1);
- model()->Add(n1);
- AppNotification* n2 = CreateNotification(true, 2);
- model()->Add(n2);
-
- SyncDataList initial_data;
- initial_data.push_back(CreateSyncData(1));
- scoped_ptr<AppNotification> n1_a(CreateNotification(
- n1->is_local(), n1->guid(), n1->extension_id(),
- n1->title() + "_changed", // different title
- n1->body(), n1->link_url().spec(), n1->link_text()));
- initial_data.push_back(
- AppNotificationManager::CreateSyncDataFromNotification(*n1_a));
-
- SyncError sync_error = model()->MergeDataAndStartSyncing(
- syncable::APP_NOTIFICATIONS,
- initial_data,
- processor());
-
- EXPECT_TRUE(sync_error.IsSet());
- EXPECT_EQ(syncable::APP_NOTIFICATIONS, sync_error.type());
- EXPECT_EQ(0, processor()->change_list_size());
-}
-
-// When an item in sync matches with a local-only item in model, an error
-// should be returned.
-TEST_F(AppNotificationManagerSyncTest, ModelAssocBothNonEmptyMatchesLocal) {
- AppNotification* n1 = CreateNotification(1);
- model()->Add(n1);
- AppNotification* n2 = CreateNotification(true, 2);
- model()->Add(n2);
-
- SyncDataList initial_data;
- initial_data.push_back(CreateSyncData(1));
- scoped_ptr<AppNotification> n2_a(CreateNotification(2));
- initial_data.push_back(
- AppNotificationManager::CreateSyncDataFromNotification(*n2_a));
-
- SyncError sync_error = model()->MergeDataAndStartSyncing(
- syncable::APP_NOTIFICATIONS,
- initial_data,
- processor());
-
- EXPECT_TRUE(sync_error.IsSet());
- EXPECT_EQ(syncable::APP_NOTIFICATIONS, sync_error.type());
- EXPECT_EQ(0, processor()->change_list_size());
-}
-
-// Process sync changes when model is empty.
-TEST_F(AppNotificationManagerSyncTest, ProcessSyncChangesEmptyModel) {
- // We initially have no data.
- model()->MergeDataAndStartSyncing(
- syncable::APP_NOTIFICATIONS,
- SyncDataList(),
- processor());
-
- // Set up a bunch of ADDs.
- SyncChangeList changes;
- changes.push_back(CreateSyncChange(
- SyncChange::ACTION_ADD, CreateNotification(1)));
- changes.push_back(CreateSyncChange(
- SyncChange::ACTION_ADD, CreateNotification(2)));
- changes.push_back(CreateSyncChange(
- SyncChange::ACTION_ADD, CreateNotification(3)));
-
- model()->ProcessSyncChanges(FROM_HERE, changes);
-
- EXPECT_EQ(3U, model()->GetAllSyncData(syncable::APP_NOTIFICATIONS).size());
- EXPECT_EQ(0, processor()->change_list_size());
-}
-
-// Process sync changes when model is not empty.
-TEST_F(AppNotificationManagerSyncTest, ProcessSyncChangesNonEmptyModel) {
- AppNotification* n1 = CreateNotification(1);
- model()->Add(n1);
- AppNotification* n2 = CreateNotification(2);
- model()->Add(n2);
- model()->MergeDataAndStartSyncing(
- syncable::APP_NOTIFICATIONS,
- SyncDataList(),
- processor());
-
- // Some adds and some deletes.
- SyncChangeList changes;
- changes.push_back(CreateSyncChange(
- SyncChange::ACTION_ADD, CreateNotification(3)));
- changes.push_back(CreateSyncChange(
- SyncChange::ACTION_DELETE, CreateNotification(*n1)));
- changes.push_back(CreateSyncChange(
- SyncChange::ACTION_ADD, CreateNotification(4)));
-
- model()->ProcessSyncChanges(FROM_HERE, changes);
-
- EXPECT_EQ(3U, model()->GetAllSyncData(syncable::APP_NOTIFICATIONS).size());
- EXPECT_EQ(2, processor()->change_list_size());
-}
-
-// Process sync changes should return error if model association is not done.
-TEST_F(AppNotificationManagerSyncTest,
- ProcessSyncChangesErrorModelAssocNotDone) {
- SyncChangeList changes;
-
- SyncError sync_error = model()->ProcessSyncChanges(FROM_HERE, changes);
- EXPECT_TRUE(sync_error.IsSet());
- EXPECT_EQ(syncable::APP_NOTIFICATIONS, sync_error.type());
- EXPECT_EQ(0, processor()->change_list_size());
-}
-
-// Stop syncing sets state correctly.
-TEST_F(AppNotificationManagerSyncTest, StopSyncing) {
- EXPECT_FALSE(model()->sync_processor_);
- EXPECT_FALSE(model()->models_associated_);
-
- model()->MergeDataAndStartSyncing(
- syncable::APP_NOTIFICATIONS,
- SyncDataList(),
- processor());
-
- EXPECT_TRUE(model()->sync_processor_);
- EXPECT_TRUE(model()->models_associated_);
-
- model()->StopSyncing(syncable::APP_NOTIFICATIONS);
- EXPECT_FALSE(model()->sync_processor_);
- EXPECT_FALSE(model()->models_associated_);
-}
-
-// Adds get pushed to sync but local only are skipped.
-TEST_F(AppNotificationManagerSyncTest, AddsGetsSynced) {
- model()->MergeDataAndStartSyncing(
- syncable::APP_NOTIFICATIONS,
- SyncDataList(),
- processor());
-
- AppNotification* n1 = CreateNotification(1);
- model()->Add(n1);
- AppNotification* n2 = CreateNotification(2);
- model()->Add(n2);
- AppNotification* n3 = CreateNotification(true, 2);
- model()->Add(n3);
-
- EXPECT_EQ(2, processor()->change_list_size());
- EXPECT_TRUE(processor()->ContainsGuid(n1->guid()));
- SyncChange c1 = processor()->GetChangeByGuid(n1->guid());
- AssertSyncChange(c1, SyncChange::ACTION_ADD, *n1);
- SyncChange c2 = processor()->GetChangeByGuid(n2->guid());
- AssertSyncChange(c2, SyncChange::ACTION_ADD, *n2);
-}
-
-// Clear all gets pushed to sync.
-TEST_F(AppNotificationManagerSyncTest, ClearAllGetsSynced) {
- const std::string& ext_id = "e1";
- scoped_ptr<AppNotification> n1(CreateNotification(false, 1, ext_id));
- scoped_ptr<AppNotification> n2(CreateNotification(false, 2, ext_id));
- scoped_ptr<AppNotification> n3(CreateNotification(false, 3, ext_id));
- scoped_ptr<AppNotification> n4(CreateNotification(4));
-
- SyncDataList initial_data;
- initial_data.push_back(
- AppNotificationManager::CreateSyncDataFromNotification(*n1));
- initial_data.push_back(
- AppNotificationManager::CreateSyncDataFromNotification(*n2));
- initial_data.push_back(
- AppNotificationManager::CreateSyncDataFromNotification(*n3));
- initial_data.push_back(
- AppNotificationManager::CreateSyncDataFromNotification(*n4));
- model()->MergeDataAndStartSyncing(
- syncable::APP_NOTIFICATIONS,
- initial_data,
- processor());
-
- model()->ClearAll(ext_id);
-
- EXPECT_EQ(3, processor()->change_list_size());
- EXPECT_TRUE(processor()->ContainsGuid(n1->guid()));
- SyncChange c1 = processor()->GetChangeByGuid(n1->guid());
- AssertSyncChange(c1, SyncChange::ACTION_DELETE, *n1);
- SyncChange c2 = processor()->GetChangeByGuid(n2->guid());
- AssertSyncChange(c2, SyncChange::ACTION_DELETE, *n2);
- SyncChange c3 = processor()->GetChangeByGuid(n3->guid());
- AssertSyncChange(c3, SyncChange::ACTION_DELETE, *n3);
-}
diff --git a/chrome/browser/extensions/app_notification_manager_unittest.cc b/chrome/browser/extensions/app_notification_manager_unittest.cc
index cdc2ea0..37aa6c6 100644
--- a/chrome/browser/extensions/app_notification_manager_unittest.cc
+++ b/chrome/browser/extensions/app_notification_manager_unittest.cc
@@ -71,18 +71,14 @@ class AppNotificationManagerTest : public testing::Test {
TEST_F(AppNotificationManagerTest, Simple) {
std::string id = extension_test_util::MakeId("whatever");
AppNotificationList list;
- util::AddNotifications(&list, id, 2, "foo");
- EXPECT_TRUE(util::AddCopiesFromList(mgr_.get(), list));
+ util::AddNotifications(&list, 2, "foo");
+ util::AddCopiesFromList(mgr_.get(), id, list);
// Cause |mgr_| to be recreated, re-reading from its storage.
InitializeManager();
const AppNotification* tmp = mgr_->GetLast(id);
- ASSERT_TRUE(tmp);
- EXPECT_EQ(list[1]->guid(), tmp->guid());
- EXPECT_EQ(list[1]->extension_id(), tmp->extension_id());
- EXPECT_EQ(list[1]->is_local(), tmp->is_local());
- EXPECT_TRUE(list[1]->Equals(*tmp));
+ EXPECT_TRUE(tmp && list[1]->Equals(*tmp));
const AppNotificationList* tmp_list = mgr_->GetAll(id);
ASSERT_TRUE(tmp_list != NULL);
util::ExpectListsEqual(list, *tmp_list);
@@ -105,10 +101,10 @@ TEST_F(AppNotificationManagerTest, MAYBE_ExtensionUninstall) {
std::string id2 = extension_test_util::MakeId("id2");
AppNotificationList list1;
AppNotificationList list2;
- util::AddNotifications(&list1, id1, 5, "foo1");
- util::AddNotifications(&list2, id2, 3, "foo2");
- util::AddCopiesFromList(mgr_.get(), list1);
- util::AddCopiesFromList(mgr_.get(), list2);
+ util::AddNotifications(&list1, 5, "foo1");
+ util::AddNotifications(&list2, 3, "foo2");
+ util::AddCopiesFromList(mgr_.get(), id1, list1);
+ util::AddCopiesFromList(mgr_.get(), id2, list2);
util::ExpectListsEqual(list1, *mgr_->GetAll(id1));
util::ExpectListsEqual(list2, *mgr_->GetAll(id2));
diff --git a/chrome/browser/extensions/app_notification_storage_unittest.cc b/chrome/browser/extensions/app_notification_storage_unittest.cc
index 2fcb251..84b836f 100644
--- a/chrome/browser/extensions/app_notification_storage_unittest.cc
+++ b/chrome/browser/extensions/app_notification_storage_unittest.cc
@@ -62,7 +62,7 @@ TEST_F(AppNotificationStorageTest, Basics) {
// Add some items.
AppNotificationList list;
- util::AddNotifications(&list, id1, 2, "whatever");
+ util::AddNotifications(&list, 2, "whatever");
EXPECT_TRUE(storage_->Set(id1, list));
EXPECT_TRUE(DatabaseExistsOnDisk());
@@ -82,12 +82,12 @@ TEST_F(AppNotificationStorageTest, MultipleExtensions) {
// Add items for id1.
AppNotificationList list1;
- util::AddNotifications(&list1, id1, 2, "one");
+ util::AddNotifications(&list1, 2, "one");
EXPECT_TRUE(storage_->Set(id1, list1));
// Add items for id2.
AppNotificationList list2;
- util::AddNotifications(&list2, id2, 3, "two");
+ util::AddNotifications(&list2, 3, "two");
EXPECT_TRUE(storage_->Set(id2, list2));
// Verify the items are present
@@ -124,8 +124,8 @@ TEST_F(AppNotificationStorageTest, ReplaceExisting) {
std::string id = extension_test_util::MakeId("1");
AppNotificationList list1;
AppNotificationList list2;
- util::AddNotifications(&list1, id, 5, "one");
- util::AddNotifications(&list2, id, 7, "two");
+ util::AddNotifications(&list1, 5, "one");
+ util::AddNotifications(&list2, 7, "two");
// Put list1 in, then replace with list2 and verify we get list2 back.
EXPECT_TRUE(storage_->Set(id, list1));
diff --git a/chrome/browser/extensions/app_notification_test_util.cc b/chrome/browser/extensions/app_notification_test_util.cc
index acef4e1..a148e50 100644
--- a/chrome/browser/extensions/app_notification_test_util.cc
+++ b/chrome/browser/extensions/app_notification_test_util.cc
@@ -21,15 +21,12 @@ void ExpectListsEqual(const AppNotificationList& one,
}
void AddNotifications(AppNotificationList* list,
- const std::string& extension_id,
int count,
- const std::string& prefix) {
+ std::string prefix) {
for (int i = 0; i < count; i++) {
- std::string guid = prefix + "_guid_" + IntToString(i);
std::string title = prefix + "_title_" + IntToString(i);
std::string body = prefix + "_body_" + IntToString(i);
- AppNotification* item = new AppNotification(
- true, guid, extension_id, title, body);
+ AppNotification* item = new AppNotification(title, body);
if (i % 2 == 0) {
item->set_link_url(GURL("http://www.example.com/" + prefix));
item->set_link_text(prefix + "_link_" + IntToString(i));
@@ -39,23 +36,20 @@ void AddNotifications(AppNotificationList* list,
}
AppNotification* CopyAppNotification(const AppNotification& source) {
- AppNotification* copy = new AppNotification(
- source.is_local(), source.guid(), source.extension_id(),
- source.title(), source.body());
+ AppNotification* copy = new AppNotification(source.title(), source.body());
copy->set_link_url(source.link_url());
copy->set_link_text(source.link_text());
return copy;
}
-bool AddCopiesFromList(AppNotificationManager* manager,
+void AddCopiesFromList(AppNotificationManager* manager,
+ const std::string& extension_id,
const AppNotificationList& list) {
- bool result = true;
for (AppNotificationList::const_iterator i = list.begin();
i != list.end();
++i) {
- result = result && manager->Add(CopyAppNotification(*(i->get())));
+ manager->Add(extension_id, CopyAppNotification(*(i->get())));
}
- return result;
}
} // namespace app_notification_test_util
diff --git a/chrome/browser/extensions/app_notification_test_util.h b/chrome/browser/extensions/app_notification_test_util.h
index d17d0b6..0f38e5a 100644
--- a/chrome/browser/extensions/app_notification_test_util.h
+++ b/chrome/browser/extensions/app_notification_test_util.h
@@ -20,15 +20,16 @@ void ExpectListsEqual(const AppNotificationList& one,
// Helper for inserting |count| dummy notifications with |prefix| in their
// title and body into |list|.
void AddNotifications(AppNotificationList* list,
- const std::string& extension_id,
int count,
- const std::string& prefix);
+ std::string prefix);
// Copy the contents of |source| into a new object.
AppNotification* CopyAppNotification(const AppNotification& source);
-// Adds a copy of each item in |list| to |manager|.
-bool AddCopiesFromList(AppNotificationManager* manager,
+// Adds a copy of each item in |list| to |manager| using |extension_id| as the
+// extension id.
+void AddCopiesFromList(AppNotificationManager* manager,
+ const std::string& extension_id,
const AppNotificationList& list);
} // namespace app_notification_test_util
diff --git a/chrome/browser/extensions/extension_app_api.cc b/chrome/browser/extensions/extension_app_api.cc
index 45e666a..d89526c 100644
--- a/chrome/browser/extensions/extension_app_api.cc
+++ b/chrome/browser/extensions/extension_app_api.cc
@@ -45,8 +45,7 @@ bool AppNotifyFunction::RunImpl() {
if (details->HasKey(kBodyTextKey))
EXTENSION_FUNCTION_VALIDATE(details->GetString(kBodyTextKey, &body));
- scoped_ptr<AppNotification> item(new AppNotification(
- true, "", id, title, body));
+ scoped_ptr<AppNotification> item(new AppNotification(title, body));
if (details->HasKey(kLinkUrlKey)) {
std::string link_url;
@@ -69,7 +68,7 @@ bool AppNotifyFunction::RunImpl() {
AppNotificationManager* manager =
profile()->GetExtensionService()->app_notification_manager();
- manager->Add(item.release());
+ manager->Add(id, item.release());
NotificationService::current()->Notify(
chrome::NOTIFICATION_APP_NOTIFICATION_STATE_CHANGED,
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 4a71347..715b7b8 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1273,7 +1273,6 @@
'browser/event_disposition.cc',
'browser/event_disposition.h',
'browser/extensions/app_notification_manager_unittest.cc',
- 'browser/extensions/app_notification_manager_sync_unittest.cc',
'browser/extensions/app_notification_storage_unittest.cc',
'browser/extensions/app_notification_test_util.cc',
'browser/extensions/app_notify_channel_setup_unittest.cc',
diff --git a/chrome/common/chrome_notification_types.h b/chrome/common/chrome_notification_types.h
index 4dfcd1b..e6cee1b 100644
--- a/chrome/common/chrome_notification_types.h
+++ b/chrome/common/chrome_notification_types.h
@@ -538,10 +538,6 @@ enum NotificationType {
// with the extension id of the app.
NOTIFICATION_APP_NOTIFICATION_STATE_CHANGED,
- // Finished loading app notification manager.
- // The source is AppNotificationManager, and the details are NoDetails.
- NOTIFICATION_APP_NOTIFICATION_MANAGER_LOADED,
-
// Component Updater -------------------------------------------------------
// Sent when the component updater starts doing update checks. If no