blob: 2b77004c0fbbb7dda64b83e7877cb60a1131addd [file] [log] [blame]
// 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 "chrome/browser/extensions/app_notification_manager.h"
#include "base/bind.h"
#include "base/file_path.h"
#include "base/stl_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/extensions/extension.h"
#include "content/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
AppNotificationManager::AppNotificationManager(Profile* profile)
: profile_(profile) {
registrar_.Add(this,
chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
content::Source<Profile>(profile_));
}
namespace {
void DeleteStorageOnFileThread(AppNotificationStorage* storage) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
delete storage;
}
} // namespace
AppNotificationManager::~AppNotificationManager() {
// Post a task to delete our storage on the file thread.
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
base::Bind(&DeleteStorageOnFileThread, storage_.release()));
}
void AppNotificationManager::Init() {
FilePath storage_path = profile_->GetPath().AppendASCII("App Notifications");
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
base::Bind(
&AppNotificationManager::LoadOnFileThread, this, storage_path));
}
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));
if (!storage_.get())
return;
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
base::Bind(
&AppNotificationManager::SaveOnFileThread, this, extension_id, list));
}
const AppNotificationList* AppNotificationManager::GetAll(
const std::string& extension_id) {
if (ContainsKey(notifications_, extension_id))
return &notifications_[extension_id];
return NULL;
}
const AppNotification* AppNotificationManager::GetLast(
const std::string& extension_id) {
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) {
NotificationMap::iterator found = notifications_.find(extension_id);
if (found != notifications_.end())
notifications_.erase(found);
if (!storage_.get())
return;
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
base::Bind(
&AppNotificationManager::DeleteOnFileThread, this, extension_id));
}
void AppNotificationManager::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
CHECK(type == chrome::NOTIFICATION_EXTENSION_UNINSTALLED);
ClearAll(*content::Details<const std::string>(details).ptr());
}
void AppNotificationManager::LoadOnFileThread(const FilePath& storage_path) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
storage_.reset(AppNotificationStorage::Create(storage_path));
if (!storage_.get())
return;
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];
if (!storage_->Get(id, &list))
result.erase(id);
}
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(&AppNotificationManager::HandleLoadResults, this, result));
}
void AppNotificationManager::HandleLoadResults(const NotificationMap& map) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
NotificationMap::const_iterator i;
for (i = map.begin(); i != map.end(); ++i) {
const std::string& id = i->first;
const AppNotificationList& list = i->second;
if (list.empty())
continue;
notifications_[id].insert(notifications_[id].begin(),
list.begin(),
list.end());
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_APP_NOTIFICATION_STATE_CHANGED,
content::Source<Profile>(profile_),
content::Details<const std::string>(&id));
}
}
void AppNotificationManager::SaveOnFileThread(const std::string& extension_id,
const AppNotificationList& list) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
storage_->Set(extension_id, list);
}
void AppNotificationManager::DeleteOnFileThread(
const std::string& extension_id) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
storage_->Delete(extension_id);
}