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
NotificationExceptionsTableModel(DesktopNotificationService * service)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
~NotificationExceptionsTableModel()36 NotificationExceptionsTableModel::~NotificationExceptionsTableModel() {}
37
CanRemoveRows(const Rows & rows) const38 bool NotificationExceptionsTableModel::CanRemoveRows(
39 const Rows& rows) const {
40 return !rows.empty();
41 }
42
RemoveRows(const Rows & rows)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
RemoveAll()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
RowCount()69 int NotificationExceptionsTableModel::RowCount() {
70 return static_cast<int>(entries_.size());
71 }
72
GetText(int row,int column_id)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
SetObserver(ui::TableModelObserver * observer)95 void NotificationExceptionsTableModel::SetObserver(
96 ui::TableModelObserver* observer) {
97 observer_ = observer;
98 }
99
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)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
LoadEntries()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
Entry(const GURL & in_origin,ContentSetting in_setting)125 NotificationExceptionsTableModel::Entry::Entry(
126 const GURL& in_origin,
127 ContentSetting in_setting)
128 : origin(in_origin),
129 setting(in_setting) {
130 }
131
operator <(const NotificationExceptionsTableModel::Entry & b) const132 bool NotificationExceptionsTableModel::Entry::operator<(
133 const NotificationExceptionsTableModel::Entry& b) const {
134 DCHECK_NE(origin, b.origin);
135 return origin < b.origin;
136 }
137