Home | History | Annotate | Download | only in notifications
      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