// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/plugin_exceptions_table_model.h"
#include "base/auto_reset.h"
#include "base/sys_string_conversions.h"
#include "base/utf_string_conversions.h"
#include "content/common/notification_service.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/table_model_observer.h"
PluginExceptionsTableModel::PluginExceptionsTableModel(
HostContentSettingsMap* content_settings_map,
HostContentSettingsMap* otr_content_settings_map)
: map_(content_settings_map),
otr_map_(otr_content_settings_map),
updates_disabled_(false),
observer_(NULL) {
registrar_.Add(this, NotificationType::CONTENT_SETTINGS_CHANGED,
NotificationService::AllSources());
}
PluginExceptionsTableModel::~PluginExceptionsTableModel() {
}
bool PluginExceptionsTableModel::CanRemoveRows(const Rows& rows) const {
return !rows.empty();
}
void PluginExceptionsTableModel::RemoveRows(const Rows& rows) {
AutoReset<bool> tmp(&updates_disabled_, true);
bool reload_all = false;
// Iterate over the rows starting with the highest ones so we can delete
// entries from |settings_| without the other indices shifting.
for (Rows::const_reverse_iterator it = rows.rbegin();
it != rows.rend(); ++it) {
DCHECK_LT(*it, settings_.size());
SettingsEntry entry = settings_[*it];
HostContentSettingsMap* map = entry.is_otr ? otr_map_ : map_;
map->SetContentSetting(entry.pattern,
CONTENT_SETTINGS_TYPE_PLUGINS,
resources_[entry.plugin_id],
CONTENT_SETTING_DEFAULT);
settings_.erase(settings_.begin() + *it);
row_counts_[entry.plugin_id]--;
if (!reload_all) {
// If we remove the last exception for a plugin, recreate all groups
// to get correct IDs.
if (row_counts_[entry.plugin_id] == 0) {
reload_all = true;
} else {
if (observer_)
observer_->OnItemsRemoved(*it, 1);
}
}
}
if (reload_all) {
// This also notifies the observer.
ReloadSettings();
}
}
void PluginExceptionsTableModel::RemoveAll() {
AutoReset<bool> tmp(&updates_disabled_, true);
map_->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS);
if (otr_map_)
otr_map_->ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS);
ClearSettings();
if (observer_)
observer_->OnModelChanged();
}
int PluginExceptionsTableModel::RowCount() {
return settings_.size();
}
string16 PluginExceptionsTableModel::GetText(int row, int column_id) {
DCHECK_GE(row, 0);
DCHECK_LT(row, static_cast<int>(settings_.size()));
SettingsEntry& entry = settings_[row];
if (column_id == IDS_EXCEPTIONS_PATTERN_HEADER ||
column_id == IDS_EXCEPTIONS_HOSTNAME_HEADER) {
return UTF8ToUTF16(entry.pattern.AsString());
} else if (column_id == IDS_EXCEPTIONS_ACTION_HEADER) {
switch (entry.setting) {
case CONTENT_SETTING_ALLOW:
return l10n_util::GetStringUTF16(IDS_EXCEPTIONS_ALLOW_BUTTON);
case CONTENT_SETTING_BLOCK:
return l10n_util::GetStringUTF16(IDS_EXCEPTIONS_BLOCK_BUTTON);
default:
NOTREACHED();
}
} else {
NOTREACHED();
}
return string16();
}
bool PluginExceptionsTableModel::HasGroups() {
return true;
}
void PluginExceptionsTableModel::SetObserver(ui::TableModelObserver* observer) {
observer_ = observer;
}
ui::TableModel::Groups PluginExceptionsTableModel::GetGroups() {
return groups_;
}
int PluginExceptionsTableModel::GetGroupID(int row) {
DCHECK_LT(row, static_cast<int>(settings_.size()));
return settings_[row].plugin_id;
}
void PluginExceptionsTableModel::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
if (!updates_disabled_)
ReloadSettings();
}
void PluginExceptionsTableModel::ClearSettings() {
settings_.clear();
groups_.clear();
row_counts_.clear();
resources_.clear();
}
void PluginExceptionsTableModel::GetPlugins(
std::vector<webkit::npapi::PluginGroup>* plugin_groups) {
webkit::npapi::PluginList::Singleton()->GetPluginGroups(false, plugin_groups);
}
void PluginExceptionsTableModel::LoadSettings() {
int group_id = 0;
std::vector<webkit::npapi::PluginGroup> plugins;
GetPlugins(&plugins);
for (size_t i = 0; i < plugins.size(); ++i) {
std::string plugin = plugins[i].identifier();
HostContentSettingsMap::SettingsForOneType settings;
map_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
plugin,
&settings);
HostContentSettingsMap::SettingsForOneType otr_settings;
if (otr_map_) {
otr_map_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
plugin,
&otr_settings);
}
string16 title = plugins[i].GetGroupName();
for (HostContentSettingsMap::SettingsForOneType::iterator setting_it =
settings.begin();
setting_it != settings.end(); ++setting_it) {
SettingsEntry entry = {
setting_it->first,
group_id,
setting_it->second,
false
};
settings_.push_back(entry);
}
for (HostContentSettingsMap::SettingsForOneType::iterator setting_it =
otr_settings.begin();
setting_it != otr_settings.end(); ++setting_it) {
SettingsEntry entry = {
setting_it->first,
group_id,
setting_it->second,
true
};
settings_.push_back(entry);
}
int num_plugins = settings.size() + otr_settings.size();
if (num_plugins > 0) {
Group group = { title, group_id++ };
groups_.push_back(group);
resources_.push_back(plugin);
row_counts_.push_back(num_plugins);
}
}
}
void PluginExceptionsTableModel::ReloadSettings() {
ClearSettings();
LoadSettings();
if (observer_)
observer_->OnModelChanged();
}