summaryrefslogtreecommitdiffstats
path: root/chrome/browser/notifications
diff options
context:
space:
mode:
authorthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-06 16:45:22 +0000
committerthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-06 16:45:22 +0000
commitf4192f2d3de41612744b932b9f9cabdd32db7416 (patch)
tree1c481baaf1ebf329c8b2d966e40d0f2f58ab201c /chrome/browser/notifications
parent75d2456a90b4cffed0a0c99bd0444087e8c7c252 (diff)
downloadchromium_src-f4192f2d3de41612744b932b9f9cabdd32db7416.zip
chromium_src-f4192f2d3de41612744b932b9f9cabdd32db7416.tar.gz
chromium_src-f4192f2d3de41612744b932b9f9cabdd32db7416.tar.bz2
Backend changes for notifications content settings.
NotificationExceptionsTableModel is now functional, and DesktopNotificationService::GetContentSetting contains the new permission behavior. Both aren't used anywhere yet, so still no functionality change (but this is the last CL without functionality changes). Also add a ton of tests. BUG=45547 TEST=unit tests Review URL: http://codereview.chromium.org/2868042 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51669 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/notifications')
-rw-r--r--chrome/browser/notifications/desktop_notification_service.cc123
-rw-r--r--chrome/browser/notifications/desktop_notification_service.h19
-rw-r--r--chrome/browser/notifications/desktop_notification_service_unittest.cc231
-rw-r--r--chrome/browser/notifications/notification_exceptions_table_model.cc59
-rw-r--r--chrome/browser/notifications/notification_exceptions_table_model.h1
-rw-r--r--chrome/browser/notifications/notification_exceptions_table_model_unittest.cc89
-rw-r--r--chrome/browser/notifications/notifications_prefs_cache.h2
7 files changed, 458 insertions, 66 deletions
diff --git a/chrome/browser/notifications/desktop_notification_service.cc b/chrome/browser/notifications/desktop_notification_service.cc
index 56418da..ade3954 100644
--- a/chrome/browser/notifications/desktop_notification_service.cc
+++ b/chrome/browser/notifications/desktop_notification_service.cc
@@ -227,18 +227,8 @@ void DesktopNotificationService::InitPrefs() {
if (!profile_->IsOffTheRecord()) {
default_content_setting = IntToContentSetting(
prefs->GetInteger(prefs::kDesktopNotificationDefaultContentSetting));
-
- const ListValue* allowed_sites =
- prefs->GetList(prefs::kDesktopNotificationAllowedOrigins);
- if (allowed_sites)
- NotificationsPrefsCache::ListValueToGurlVector(*allowed_sites,
- &allowed_origins);
-
- const ListValue* denied_sites =
- prefs->GetList(prefs::kDesktopNotificationDeniedOrigins);
- if (denied_sites)
- NotificationsPrefsCache::ListValueToGurlVector(*denied_sites,
- &denied_origins);
+ allowed_origins = GetAllowedOrigins();
+ denied_origins = GetBlockedOrigins();
}
prefs_cache_ = new NotificationsPrefsCache();
@@ -300,13 +290,7 @@ void DesktopNotificationService::Observe(NotificationType type,
std::wstring* name = Details<std::wstring>(details).ptr();
if (0 == name->compare(prefs::kDesktopNotificationAllowedOrigins)) {
- const ListValue* allowed_sites =
- prefs->GetList(prefs::kDesktopNotificationAllowedOrigins);
- std::vector<GURL> allowed_origins;
- if (allowed_sites) {
- NotificationsPrefsCache::ListValueToGurlVector(*allowed_sites,
- &allowed_origins);
- }
+ std::vector<GURL> allowed_origins(GetAllowedOrigins());
// Schedule a cache update on the IO thread.
ChromeThread::PostTask(
ChromeThread::IO, FROM_HERE,
@@ -315,13 +299,7 @@ void DesktopNotificationService::Observe(NotificationType type,
&NotificationsPrefsCache::SetCacheAllowedOrigins,
allowed_origins));
} else if (0 == name->compare(prefs::kDesktopNotificationDeniedOrigins)) {
- const ListValue* denied_sites =
- prefs->GetList(prefs::kDesktopNotificationDeniedOrigins);
- std::vector<GURL> denied_origins;
- if (denied_sites) {
- NotificationsPrefsCache::ListValueToGurlVector(*denied_sites,
- &denied_origins);
- }
+ std::vector<GURL> denied_origins(GetBlockedOrigins());
// Schedule a cache update on the IO thread.
ChromeThread::PostTask(
ChromeThread::IO, FROM_HERE,
@@ -352,6 +330,10 @@ void DesktopNotificationService::PersistPermissionChange(
PrefService* prefs = profile_->GetPrefs();
+ // |Observe()| updates the whole permission set in the cache, but only a
+ // single origin has changed. Hence, callers of this method manually
+ // schedule a task to update the prefs cache, and the prefs observer is
+ // disabled while the update runs.
StopObserving();
bool allowed_changed = false;
@@ -393,7 +375,7 @@ void DesktopNotificationService::PersistPermissionChange(
// list that changed.
if (allowed_changed || denied_changed) {
if (allowed_changed) {
- ScopedPrefUpdate updateAllowed(
+ ScopedPrefUpdate update_allowed(
prefs, prefs::kDesktopNotificationAllowedOrigins);
}
if (denied_changed) {
@@ -423,6 +405,93 @@ void DesktopNotificationService::SetDefaultContentSetting(
// The cache is updated through the notification observer.
}
+std::vector<GURL> DesktopNotificationService::GetAllowedOrigins() {
+ std::vector<GURL> allowed_origins;
+ PrefService* prefs = profile_->GetPrefs();
+ const ListValue* allowed_sites =
+ prefs->GetList(prefs::kDesktopNotificationAllowedOrigins);
+ if (allowed_sites) {
+ NotificationsPrefsCache::ListValueToGurlVector(*allowed_sites,
+ &allowed_origins);
+ }
+ return allowed_origins;
+}
+
+std::vector<GURL> DesktopNotificationService::GetBlockedOrigins() {
+ std::vector<GURL> denied_origins;
+ PrefService* prefs = profile_->GetPrefs();
+ const ListValue* denied_sites =
+ prefs->GetList(prefs::kDesktopNotificationDeniedOrigins);
+ if (denied_sites) {
+ NotificationsPrefsCache::ListValueToGurlVector(*denied_sites,
+ &denied_origins);
+ }
+ return denied_origins;
+}
+
+void DesktopNotificationService::ResetAllowedOrigin(const GURL& origin) {
+ if (profile_->IsOffTheRecord())
+ return;
+
+ // Since this isn't called often, let the normal observer behavior update the
+ // cache in this case.
+ PrefService* prefs = profile_->GetPrefs();
+ ListValue* allowed_sites =
+ prefs->GetMutableList(prefs::kDesktopNotificationAllowedOrigins);
+ {
+ StringValue value(origin.spec());
+ int removed_index = allowed_sites->Remove(value);
+ DCHECK_NE(-1, removed_index) << origin << " was not allowed";
+ ScopedPrefUpdate update_allowed(
+ prefs, prefs::kDesktopNotificationAllowedOrigins);
+ }
+ prefs->ScheduleSavePersistentPrefs();
+}
+
+void DesktopNotificationService::ResetBlockedOrigin(const GURL& origin) {
+ if (profile_->IsOffTheRecord())
+ return;
+
+ // Since this isn't called often, let the normal observer behavior update the
+ // cache in this case.
+ PrefService* prefs = profile_->GetPrefs();
+ ListValue* denied_sites =
+ prefs->GetMutableList(prefs::kDesktopNotificationDeniedOrigins);
+ {
+ StringValue value(origin.spec());
+ int removed_index = denied_sites->Remove(value);
+ DCHECK_NE(-1, removed_index) << origin << " was not blocked";
+ ScopedPrefUpdate update_allowed(
+ prefs, prefs::kDesktopNotificationDeniedOrigins);
+ }
+ prefs->ScheduleSavePersistentPrefs();
+}
+
+void DesktopNotificationService::ResetAllOrigins() {
+ PrefService* prefs = profile_->GetPrefs();
+ prefs->ClearPref(prefs::kDesktopNotificationAllowedOrigins);
+ prefs->ClearPref(prefs::kDesktopNotificationDeniedOrigins);
+}
+
+ContentSetting DesktopNotificationService::GetContentSetting(
+ const GURL& origin) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ if (profile_->IsOffTheRecord())
+ return kDefaultSetting;
+
+ std::vector<GURL> allowed_origins(GetAllowedOrigins());
+ if (std::find(allowed_origins.begin(), allowed_origins.end(), origin) !=
+ allowed_origins.end())
+ return CONTENT_SETTING_ALLOW;
+
+ std::vector<GURL> denied_origins(GetBlockedOrigins());
+ if (std::find(denied_origins.begin(), denied_origins.end(), origin) !=
+ denied_origins.end())
+ return CONTENT_SETTING_BLOCK;
+
+ return GetDefaultContentSetting();
+}
+
void DesktopNotificationService::RequestPermission(
const GURL& origin, int process_id, int route_id, int callback_context,
TabContents* tab) {
diff --git a/chrome/browser/notifications/desktop_notification_service.h b/chrome/browser/notifications/desktop_notification_service.h
index e2be439..3f97425 100644
--- a/chrome/browser/notifications/desktop_notification_service.h
+++ b/chrome/browser/notifications/desktop_notification_service.h
@@ -86,9 +86,26 @@ class DesktopNotificationService : public NotificationObserver {
static string16 CreateDataUrl(const GURL& icon_url, const string16& title,
const string16& body);
+ // The default content setting determines how to handle origins that haven't
+ // been allowed or denied yet.
ContentSetting GetDefaultContentSetting();
void SetDefaultContentSetting(ContentSetting setting);
+ // Returns all origins that explicitly have been allowed.
+ std::vector<GURL> GetAllowedOrigins();
+
+ // Returns all origins that explicitly have been denied.
+ std::vector<GURL> GetBlockedOrigins();
+
+ // Removes an origin from the "explicitly allowed" set.
+ void ResetAllowedOrigin(const GURL& origin);
+
+ // Removes an origin from the "explicitly denied" set.
+ void ResetBlockedOrigin(const GURL& origin);
+
+ // Clears the sets of explicitly allowed and denied origins.
+ void ResetAllOrigins();
+
static void RegisterUserPrefs(PrefService* user_prefs);
private:
void InitPrefs();
@@ -103,6 +120,8 @@ class DesktopNotificationService : public NotificationObserver {
// itself when dealing with extensions.
std::wstring DisplayNameForOrigin(const GURL& origin);
+ ContentSetting GetContentSetting(const GURL& origin);
+
// The profile which owns this object.
Profile* profile_;
diff --git a/chrome/browser/notifications/desktop_notification_service_unittest.cc b/chrome/browser/notifications/desktop_notification_service_unittest.cc
index 4e0a705..3af8b0f 100644
--- a/chrome/browser/notifications/desktop_notification_service_unittest.cc
+++ b/chrome/browser/notifications/desktop_notification_service_unittest.cc
@@ -4,70 +4,243 @@
#include "chrome/browser/notifications/desktop_notification_service.h"
-#include "base/task.h"
+#include "base/ref_counted.h"
#include "base/waitable_event.h"
#include "chrome/browser/notifications/notifications_prefs_cache.h"
+#include "chrome/browser/pref_service.h"
#include "chrome/browser/renderer_host/test/test_render_view_host.h"
+#include "chrome/browser/scoped_pref_update.h"
+#include "chrome/common/pref_names.h"
#include "chrome/test/testing_profile.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPresenter.h"
namespace {
-class WaitTask : public Task {
+// NotificationsPrefsCache wants to be called on the IO thread. This class
+// routes calls to the cache on the IO thread.
+class ThreadProxy : public base::RefCountedThreadSafe<ThreadProxy> {
public:
- WaitTask(base::WaitableEvent* event)
- : event_(event) {
+ ThreadProxy()
+ : io_event_(false, false),
+ ui_event_(false, false) {
+ // The current message loop was already initalized by the test superclass.
+ ui_thread_.reset(
+ new ChromeThread(ChromeThread::UI, MessageLoop::current()));
+
+ // Create IO thread, start its message loop.
+ io_thread_.reset(new ChromeThread(ChromeThread::IO));
+ io_thread_->Start();
+
+ // Calling PauseIOThread() here isn't safe, because the runnable method
+ // could complete before the constructor is done, deleting |this|.
}
- virtual void Run() {
- event_->Wait();
+
+ int CacheHasPermission(NotificationsPrefsCache* cache, const GURL& url) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &ThreadProxy::CacheHasPermissionIO,
+ cache, url));
+ io_event_.Signal();
+ ui_event_.Wait(); // Wait for IO thread to be done.
+ ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &ThreadProxy::PauseIOThreadIO));
+
+ return permission_;
+ }
+
+ void PauseIOThread() {
+ ChromeThread::PostTask(ChromeThread::IO, FROM_HERE,
+ NewRunnableMethod(this, &ThreadProxy::PauseIOThreadIO));
+ }
+
+ void DrainIOThread() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ io_event_.Signal();
+ io_thread_->Stop();
}
private:
- base::WaitableEvent* event_;
+ friend class base::RefCountedThreadSafe<ThreadProxy>;
+ ~ThreadProxy() {
+ DrainIOThread();
+ }
+
+ void PauseIOThreadIO() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ io_event_.Wait();
+ }
+
+ void CacheHasPermissionIO(NotificationsPrefsCache* cache, const GURL& url) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ permission_ = cache->HasPermission(url);
+ ui_event_.Signal();
+ }
+
+ base::WaitableEvent io_event_;
+ base::WaitableEvent ui_event_;
+ scoped_ptr<ChromeThread> ui_thread_;
+ scoped_ptr<ChromeThread> io_thread_;
+
+ int permission_;
};
class DesktopNotificationServiceTest : public RenderViewHostTestHarness {
public:
- DesktopNotificationServiceTest()
- : event_(false, false) {
+ DesktopNotificationServiceTest() {
}
- base::WaitableEvent event_;
-};
-TEST_F(DesktopNotificationServiceTest, DefaultContentSettingSentToCache) {
- // The current message loop was already initalized by the superclass.
- ChromeThread ui_thread(ChromeThread::UI, MessageLoop::current());
+ virtual void SetUp() {
+ RenderViewHostTestHarness::SetUp();
+ proxy_ = new ThreadProxy;
+ proxy_->PauseIOThread();
+
+ // Creates the service, calls InitPrefs() on it which loads data from the
+ // profile into the cache and then puts the cache in io thread mode.
+ service_ = profile()->GetDesktopNotificationService();
+ cache_ = service_->prefs_cache();
+ }
- // Create IO thread, start its message loop.
- ChromeThread io_thread(ChromeThread::IO);
- io_thread.Start();
- ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, new WaitTask(&event_));
+ virtual void TearDown() {
+ // The io thread's waiting on the io_event_ might hold a ref to |proxy_|,
+ // preventing its destruction. Clear that ref.
+ proxy_->DrainIOThread();
+ RenderViewHostTestHarness::TearDown();
+ }
- // Creates the service, calls InitPrefs() on it which loads data from the
- // profile into the cache and then puts the cache in io thread mode.
- DesktopNotificationService* service =
- profile()->GetDesktopNotificationService();
- NotificationsPrefsCache* cache = service->prefs_cache();
+ DesktopNotificationService* service_;
+ NotificationsPrefsCache* cache_;
+ scoped_refptr<ThreadProxy> proxy_;
+};
+TEST_F(DesktopNotificationServiceTest, DefaultContentSettingSentToCache) {
// The default pref registered in DesktopNotificationService is "ask",
// and that's what sent to the cache.
- EXPECT_EQ(CONTENT_SETTING_ASK, cache->CachedDefaultContentSetting());
+ EXPECT_EQ(CONTENT_SETTING_ASK, cache_->CachedDefaultContentSetting());
// Change the default content setting. This will post a task on the IO thread
// to update the cache.
- service->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
+ service_->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
// The updated pref shouldn't be sent to the cache immediately.
- EXPECT_EQ(CONTENT_SETTING_ASK, cache->CachedDefaultContentSetting());
+ EXPECT_EQ(CONTENT_SETTING_ASK, cache_->CachedDefaultContentSetting());
// Run IO thread tasks.
- event_.Signal();
- io_thread.Stop();
+ proxy_->DrainIOThread();
// Now that IO thread events have been processed, it should be there.
- EXPECT_EQ(CONTENT_SETTING_BLOCK, cache->CachedDefaultContentSetting());
+ EXPECT_EQ(CONTENT_SETTING_BLOCK, cache_->CachedDefaultContentSetting());
+}
+
+TEST_F(DesktopNotificationServiceTest, GrantPermissionSentToCache) {
+ GURL url("http://allowed.com");
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
+ proxy_->CacheHasPermission(cache_, url));
+
+ service_->GrantPermission(url);
+
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionAllowed,
+ proxy_->CacheHasPermission(cache_, url));
+}
+
+TEST_F(DesktopNotificationServiceTest, DenyPermissionSentToCache) {
+ GURL url("http://denied.com");
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
+ proxy_->CacheHasPermission(cache_, url));
+
+ service_->DenyPermission(url);
+
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionDenied,
+ proxy_->CacheHasPermission(cache_, url));
+}
+
+TEST_F(DesktopNotificationServiceTest, PrefChangesSentToCache) {
+ PrefService* prefs = profile()->GetPrefs();
+
+ ListValue* allowed_sites =
+ prefs->GetMutableList(prefs::kDesktopNotificationAllowedOrigins);
+ {
+ allowed_sites->Append(new StringValue(GURL("http://allowed.com").spec()));
+ ScopedPrefUpdate updateAllowed(
+ prefs, prefs::kDesktopNotificationAllowedOrigins);
+ }
+
+ ListValue* denied_sites =
+ prefs->GetMutableList(prefs::kDesktopNotificationDeniedOrigins);
+ {
+ denied_sites->Append(new StringValue(GURL("http://denied.com").spec()));
+ ScopedPrefUpdate updateDenied(
+ prefs, prefs::kDesktopNotificationDeniedOrigins);
+ }
+
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionAllowed,
+ proxy_->CacheHasPermission(cache_, GURL("http://allowed.com")));
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionDenied,
+ proxy_->CacheHasPermission(cache_, GURL("http://denied.com")));
+}
+
+TEST_F(DesktopNotificationServiceTest, GetAllowedOrigins) {
+ service_->GrantPermission(GURL("http://allowed2.com"));
+ service_->GrantPermission(GURL("http://allowed.com"));
+
+ std::vector<GURL> allowed_origins(service_->GetAllowedOrigins());
+ ASSERT_EQ(2u, allowed_origins.size());
+ EXPECT_EQ(GURL("http://allowed2.com"), allowed_origins[0]);
+ EXPECT_EQ(GURL("http://allowed.com"), allowed_origins[1]);
+}
+
+TEST_F(DesktopNotificationServiceTest, GetBlockedOrigins) {
+ service_->DenyPermission(GURL("http://denied2.com"));
+ service_->DenyPermission(GURL("http://denied.com"));
+
+ std::vector<GURL> denied_origins(service_->GetBlockedOrigins());
+ ASSERT_EQ(2u, denied_origins.size());
+ EXPECT_EQ(GURL("http://denied2.com"), denied_origins[0]);
+ EXPECT_EQ(GURL("http://denied.com"), denied_origins[1]);
+}
+
+TEST_F(DesktopNotificationServiceTest, ResetAllSentToCache) {
+ GURL allowed_url("http://allowed.com");
+ service_->GrantPermission(allowed_url);
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionAllowed,
+ proxy_->CacheHasPermission(cache_, allowed_url));
+ GURL denied_url("http://denied.com");
+ service_->DenyPermission(denied_url);
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionDenied,
+ proxy_->CacheHasPermission(cache_, denied_url));
+
+ service_->ResetAllOrigins();
+
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
+ proxy_->CacheHasPermission(cache_, allowed_url));
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
+ proxy_->CacheHasPermission(cache_, denied_url));
+}
+
+TEST_F(DesktopNotificationServiceTest, ResetAllowedSentToCache) {
+ GURL allowed_url("http://allowed.com");
+ service_->GrantPermission(allowed_url);
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionAllowed,
+ proxy_->CacheHasPermission(cache_, allowed_url));
+
+ service_->ResetAllowedOrigin(allowed_url);
+
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
+ proxy_->CacheHasPermission(cache_, allowed_url));
+}
+
+TEST_F(DesktopNotificationServiceTest, ResetBlockedSentToCache) {
+ GURL denied_url("http://denied.com");
+ service_->DenyPermission(denied_url);
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionDenied,
+ proxy_->CacheHasPermission(cache_, denied_url));
+
+ service_->ResetBlockedOrigin(denied_url);
+
+ EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
+ proxy_->CacheHasPermission(cache_, denied_url));
}
} // namespace
diff --git a/chrome/browser/notifications/notification_exceptions_table_model.cc b/chrome/browser/notifications/notification_exceptions_table_model.cc
index e8e3c08..f4e8d68 100644
--- a/chrome/browser/notifications/notification_exceptions_table_model.cc
+++ b/chrome/browser/notifications/notification_exceptions_table_model.cc
@@ -8,6 +8,7 @@
#include "app/l10n_util_collator.h"
#include "app/table_model_observer.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/geolocation/geolocation_content_settings_map.h"
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
@@ -15,20 +16,44 @@ NotificationExceptionsTableModel::NotificationExceptionsTableModel(
DesktopNotificationService* service)
: service_(service),
observer_(NULL) {
+ std::vector<GURL> allowed(service_->GetAllowedOrigins());
+ std::vector<GURL> blocked(service_->GetBlockedOrigins());
+ entries_.reserve(allowed.size() + blocked.size());
+ for (size_t i = 0; i < allowed.size(); ++i)
+ entries_.push_back(Entry(allowed[i], CONTENT_SETTING_ALLOW));
+ for (size_t i = 0; i < blocked.size(); ++i)
+ entries_.push_back(Entry(blocked[i], CONTENT_SETTING_BLOCK));
+ sort(entries_.begin(), entries_.end());
}
bool NotificationExceptionsTableModel::CanRemoveRows(
const Rows& rows) const {
- NOTIMPLEMENTED();
- return false;
+ return !rows.empty();
}
void NotificationExceptionsTableModel::RemoveRows(const Rows& rows) {
- NOTIMPLEMENTED();
+ // This is O(n^2) in rows.size(). Since n is small, that's ok.
+ for (Rows::const_reverse_iterator i(rows.rbegin()); i != rows.rend(); ++i) {
+ size_t row = *i;
+ Entry* entry = &entries_[row];
+ if (entry->setting == CONTENT_SETTING_ALLOW) {
+ service_->ResetAllowedOrigin(entry->origin);
+ } else {
+ DCHECK_EQ(entry->setting, CONTENT_SETTING_BLOCK);
+ service_->ResetBlockedOrigin(entry->origin);
+ }
+ entries_.erase(entries_.begin() + row); // Note: |entry| is now garbage.
+ if (observer_)
+ observer_->OnItemsRemoved(row, 1);
+ }
}
void NotificationExceptionsTableModel::RemoveAll() {
- NOTIMPLEMENTED();
+ int old_row_count = RowCount();
+ entries_.clear();
+ service_->ResetAllOrigins();
+ if (observer_)
+ observer_->OnItemsRemoved(0, old_row_count);
}
int NotificationExceptionsTableModel::RowCount() {
@@ -37,7 +62,26 @@ int NotificationExceptionsTableModel::RowCount() {
std::wstring NotificationExceptionsTableModel::GetText(int row,
int column_id) {
- NOTIMPLEMENTED();
+ const Entry& entry = entries_[row];
+ if (column_id == IDS_EXCEPTIONS_HOSTNAME_HEADER) {
+ // TODO(bulach): factor out in a common function so that Notifications won't
+ // depend on Geolocation.
+ return UTF8ToWide(GeolocationContentSettingsMap::OriginToString(
+ entry.origin));
+ }
+
+ if (column_id == IDS_EXCEPTIONS_ACTION_HEADER) {
+ switch (entry.setting) {
+ case CONTENT_SETTING_ALLOW:
+ return l10n_util::GetString(IDS_EXCEPTIONS_ALLOW_BUTTON);
+ case CONTENT_SETTING_BLOCK:
+ return l10n_util::GetString(IDS_EXCEPTIONS_BLOCK_BUTTON);
+ default:
+ break;
+ }
+ }
+
+ NOTREACHED();
return std::wstring();
}
@@ -53,3 +97,8 @@ NotificationExceptionsTableModel::Entry::Entry(
setting(in_setting) {
}
+bool NotificationExceptionsTableModel::Entry::operator<(
+ const NotificationExceptionsTableModel::Entry& b) const {
+ DCHECK_NE(origin, b.origin);
+ return origin < b.origin;
+}
diff --git a/chrome/browser/notifications/notification_exceptions_table_model.h b/chrome/browser/notifications/notification_exceptions_table_model.h
index c171034..01137f7 100644
--- a/chrome/browser/notifications/notification_exceptions_table_model.h
+++ b/chrome/browser/notifications/notification_exceptions_table_model.h
@@ -31,6 +31,7 @@ class NotificationExceptionsTableModel : public RemoveRowsTableModel {
private:
struct Entry {
Entry(const GURL& origin, ContentSetting setting);
+ bool operator<(const Entry& b) const;
GURL origin;
ContentSetting setting;
diff --git a/chrome/browser/notifications/notification_exceptions_table_model_unittest.cc b/chrome/browser/notifications/notification_exceptions_table_model_unittest.cc
index a10ce71..6919b0b 100644
--- a/chrome/browser/notifications/notification_exceptions_table_model_unittest.cc
+++ b/chrome/browser/notifications/notification_exceptions_table_model_unittest.cc
@@ -4,13 +4,13 @@
#include "chrome/browser/notifications/notification_exceptions_table_model.h"
+#include "app/l10n_util.h"
#include "chrome/browser/renderer_host/test/test_render_view_host.h"
#include "chrome/test/testing_profile.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"
-class NotificationExceptionsTableModelTest
- : public RenderViewHostTestHarness {
+class NotificationExceptionsTableModelTest : public RenderViewHostTestHarness {
public:
NotificationExceptionsTableModelTest()
: ui_thread_(ChromeThread::UI, MessageLoop::current()) {
@@ -21,6 +21,7 @@ class NotificationExceptionsTableModelTest
virtual void SetUp() {
RenderViewHostTestHarness::SetUp();
+ service_ = profile()->GetDesktopNotificationService();
ResetModel();
}
@@ -30,15 +31,95 @@ class NotificationExceptionsTableModelTest
}
virtual void ResetModel() {
- model_.reset(new NotificationExceptionsTableModel(
- profile()->GetDesktopNotificationService()));
+ model_.reset(new NotificationExceptionsTableModel(service_));
+ }
+
+ virtual void FillData() {
+ service_->GrantPermission(GURL("http://e-allowed2.com"));
+ service_->GrantPermission(GURL("http://allowed.com"));
+
+ service_->DenyPermission(GURL("http://denied2.com"));
+ service_->DenyPermission(GURL("http://denied.com"));
+ service_->DenyPermission(GURL("http://f-denied3.com"));
+
+ ResetModel();
}
protected:
ChromeThread ui_thread_;
scoped_ptr<NotificationExceptionsTableModel> model_;
+ DesktopNotificationService* service_;
};
TEST_F(NotificationExceptionsTableModelTest, CanCreate) {
EXPECT_EQ(0, model_->RowCount());
}
+
+TEST_F(NotificationExceptionsTableModelTest, RemoveAll) {
+ FillData();
+ EXPECT_EQ(2u, service_->GetAllowedOrigins().size());
+ EXPECT_EQ(3u, service_->GetBlockedOrigins().size());
+ EXPECT_EQ(5, model_->RowCount());
+
+ model_->RemoveAll();
+ EXPECT_EQ(0, model_->RowCount());
+
+ EXPECT_EQ(0u, service_->GetAllowedOrigins().size());
+ EXPECT_EQ(0u, service_->GetBlockedOrigins().size());
+}
+
+TEST_F(NotificationExceptionsTableModelTest, AlphabeticalOrder) {
+ FillData();
+ EXPECT_EQ(5, model_->RowCount());
+
+ EXPECT_EQ(L"allowed.com",
+ model_->GetText(0, IDS_EXCEPTIONS_HOSTNAME_HEADER));
+ EXPECT_EQ(l10n_util::GetString(IDS_EXCEPTIONS_ALLOW_BUTTON),
+ model_->GetText(0, IDS_EXCEPTIONS_ACTION_HEADER));
+
+ EXPECT_EQ(L"denied.com",
+ model_->GetText(1, IDS_EXCEPTIONS_HOSTNAME_HEADER));
+ EXPECT_EQ(l10n_util::GetString(IDS_EXCEPTIONS_BLOCK_BUTTON),
+ model_->GetText(1, IDS_EXCEPTIONS_ACTION_HEADER));
+
+ EXPECT_EQ(L"denied2.com",
+ model_->GetText(2, IDS_EXCEPTIONS_HOSTNAME_HEADER));
+ EXPECT_EQ(l10n_util::GetString(IDS_EXCEPTIONS_BLOCK_BUTTON),
+ model_->GetText(2, IDS_EXCEPTIONS_ACTION_HEADER));
+
+ EXPECT_EQ(L"e-allowed2.com",
+ model_->GetText(3, IDS_EXCEPTIONS_HOSTNAME_HEADER));
+ EXPECT_EQ(l10n_util::GetString(IDS_EXCEPTIONS_ALLOW_BUTTON),
+ model_->GetText(3, IDS_EXCEPTIONS_ACTION_HEADER));
+
+ EXPECT_EQ(L"f-denied3.com",
+ model_->GetText(4, IDS_EXCEPTIONS_HOSTNAME_HEADER));
+ EXPECT_EQ(l10n_util::GetString(IDS_EXCEPTIONS_BLOCK_BUTTON),
+ model_->GetText(4, IDS_EXCEPTIONS_ACTION_HEADER));
+}
+
+TEST_F(NotificationExceptionsTableModelTest, RemoveRows) {
+ FillData();
+ EXPECT_EQ(5, model_->RowCount());
+
+ {
+ RemoveRowsTableModel::Rows rows;
+ rows.insert(0); // allowed.com
+ rows.insert(3); // e-allowed2.com
+ model_->RemoveRows(rows);
+ }
+ EXPECT_EQ(3, model_->RowCount());
+ EXPECT_EQ(0u, service_->GetAllowedOrigins().size());
+ EXPECT_EQ(3u, service_->GetBlockedOrigins().size());
+
+ {
+ RemoveRowsTableModel::Rows rows;
+ rows.insert(0);
+ rows.insert(1);
+ rows.insert(2);
+ model_->RemoveRows(rows);
+ }
+ EXPECT_EQ(0, model_->RowCount());
+ EXPECT_EQ(0u, service_->GetAllowedOrigins().size());
+ EXPECT_EQ(0u, service_->GetBlockedOrigins().size());
+}
diff --git a/chrome/browser/notifications/notifications_prefs_cache.h b/chrome/browser/notifications/notifications_prefs_cache.h
index e12fa14..61bb983 100644
--- a/chrome/browser/notifications/notifications_prefs_cache.h
+++ b/chrome/browser/notifications/notifications_prefs_cache.h
@@ -23,7 +23,7 @@ class NotificationsPrefsCache
public:
NotificationsPrefsCache();
- // Once is_initialized_() is set, all accesses must happen on the IO thread.
+ // Once is_initialized() is set, all accesses must happen on the IO thread.
// Before that, all accesses need to happen on the UI thread.
void set_is_initialized(bool val) { is_initialized_ = val; }
bool is_initialized() { return is_initialized_; }