1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/notifications/notification_exceptions_table_model.h" 6 7 #include "base/auto_reset.h" 8 #include "chrome/common/content_settings.h" 9 #include "chrome/common/content_settings_helper.h" 10 #include "chrome/common/content_settings_types.h" 11 #include "chrome/common/url_constants.h" 12 #include "content/common/notification_service.h" 13 #include "content/common/notification_type.h" 14 #include "grit/generated_resources.h" 15 #include "ui/base/l10n/l10n_util.h" 16 #include "ui/base/models/table_model_observer.h" 17 18 struct NotificationExceptionsTableModel::Entry { 19 Entry(const GURL& origin, ContentSetting setting); 20 bool operator<(const Entry& b) const; 21 22 GURL origin; 23 ContentSetting setting; 24 }; 25 26 NotificationExceptionsTableModel::NotificationExceptionsTableModel( 27 DesktopNotificationService* service) 28 : service_(service), 29 updates_disabled_(false), 30 observer_(NULL) { 31 registrar_.Add(this, NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED, 32 NotificationService::AllSources()); 33 LoadEntries(); 34 } 35 36 NotificationExceptionsTableModel::~NotificationExceptionsTableModel() {} 37 38 bool NotificationExceptionsTableModel::CanRemoveRows( 39 const Rows& rows) const { 40 return !rows.empty(); 41 } 42 43 void NotificationExceptionsTableModel::RemoveRows(const Rows& rows) { 44 AutoReset<bool> tmp(&updates_disabled_, true); 45 // This is O(n^2) in rows.size(). Since n is small, that's ok. 46 for (Rows::const_reverse_iterator i(rows.rbegin()); i != rows.rend(); ++i) { 47 size_t row = *i; 48 Entry* entry = &entries_[row]; 49 if (entry->setting == CONTENT_SETTING_ALLOW) { 50 service_->ResetAllowedOrigin(entry->origin); 51 } else { 52 DCHECK_EQ(entry->setting, CONTENT_SETTING_BLOCK); 53 service_->ResetBlockedOrigin(entry->origin); 54 } 55 entries_.erase(entries_.begin() + row); // Note: |entry| is now garbage. 56 if (observer_) 57 observer_->OnItemsRemoved(row, 1); 58 } 59 } 60 61 void NotificationExceptionsTableModel::RemoveAll() { 62 AutoReset<bool> tmp(&updates_disabled_, true); 63 entries_.clear(); 64 service_->ResetAllOrigins(); 65 if (observer_) 66 observer_->OnModelChanged(); 67 } 68 69 int NotificationExceptionsTableModel::RowCount() { 70 return static_cast<int>(entries_.size()); 71 } 72 73 string16 NotificationExceptionsTableModel::GetText(int row, 74 int column_id) { 75 const Entry& entry = entries_[row]; 76 if (column_id == IDS_EXCEPTIONS_HOSTNAME_HEADER) { 77 return content_settings_helper::OriginToString16(entry.origin); 78 } 79 80 if (column_id == IDS_EXCEPTIONS_ACTION_HEADER) { 81 switch (entry.setting) { 82 case CONTENT_SETTING_ALLOW: 83 return l10n_util::GetStringUTF16(IDS_EXCEPTIONS_ALLOW_BUTTON); 84 case CONTENT_SETTING_BLOCK: 85 return l10n_util::GetStringUTF16(IDS_EXCEPTIONS_BLOCK_BUTTON); 86 default: 87 break; 88 } 89 } 90 91 NOTREACHED(); 92 return string16(); 93 } 94 95 void NotificationExceptionsTableModel::SetObserver( 96 ui::TableModelObserver* observer) { 97 observer_ = observer; 98 } 99 100 void NotificationExceptionsTableModel::Observe( 101 NotificationType type, 102 const NotificationSource& source, 103 const NotificationDetails& details) { 104 if (!updates_disabled_) { 105 DCHECK(type == NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED); 106 entries_.clear(); 107 LoadEntries(); 108 109 if (observer_) 110 observer_->OnModelChanged(); 111 } 112 } 113 114 void NotificationExceptionsTableModel::LoadEntries() { 115 std::vector<GURL> allowed(service_->GetAllowedOrigins()); 116 std::vector<GURL> blocked(service_->GetBlockedOrigins()); 117 entries_.reserve(allowed.size() + blocked.size()); 118 for (size_t i = 0; i < allowed.size(); ++i) 119 entries_.push_back(Entry(allowed[i], CONTENT_SETTING_ALLOW)); 120 for (size_t i = 0; i < blocked.size(); ++i) 121 entries_.push_back(Entry(blocked[i], CONTENT_SETTING_BLOCK)); 122 std::sort(entries_.begin(), entries_.end()); 123 } 124 125 NotificationExceptionsTableModel::Entry::Entry( 126 const GURL& in_origin, 127 ContentSetting in_setting) 128 : origin(in_origin), 129 setting(in_setting) { 130 } 131 132 bool NotificationExceptionsTableModel::Entry::operator<( 133 const NotificationExceptionsTableModel::Entry& b) const { 134 DCHECK_NE(origin, b.origin); 135 return origin < b.origin; 136 } 137