diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-06 16:45:22 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-06 16:45:22 +0000 |
commit | f4192f2d3de41612744b932b9f9cabdd32db7416 (patch) | |
tree | 1c481baaf1ebf329c8b2d966e40d0f2f58ab201c /chrome/browser/notifications | |
parent | 75d2456a90b4cffed0a0c99bd0444087e8c7c252 (diff) | |
download | chromium_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')
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_; } |